设为首页收藏本站

就爱编程论坛

 找回密码
 注册

人人连接登陆

无需注册,直接登录

用新浪微博连接

一步搞定

QQ登录

只需一步,快速开始

查看: 319|回复: 0
打印 上一主题 下一主题

php常用设计模式(策略模式/单例模式/工厂模式) [复制链接]

Rank: 9Rank: 9Rank: 9

  • TA的每日心情
    无聊
    2025-5-27 03:37:20
  • 签到天数: 366 天

    [LV.9]以坛为家II

    论坛先锋 学习至圣 荣誉成员 论坛元老 活跃之星 终极领袖

    我玩的应用:

    跳转到指定楼层
    楼主
    发表于 2012-4-2 07:02:55 |只看该作者 |倒序浏览
    之前我们的一篇《两个php常用的设计模式》介绍了php常用的设计模式,内容不够全面,本文新增了策略模式算是对其的补充吧。面向对象的程序设计理念不仅表现在的语法规则和语言特性上,更重要的是表现了一种上设计思想。面对对象的程序本身就在强调程序设计方法。当设计一个软件的时候,很多设计观念被反复地用到,甚至已经成为了一种共用的规则,这些规则通常被称为设计模式。下面要介绍的是三种最的设计模式。
      策略模式(Strategy Pattern)
      策略模式指的是程序中涉及决策控制的一种模式。例如,一段 PHP 代码用来显示一张 HTML 页面,访问者的浏览器可能会是 IE,也可能会是 Netscape。这时程序就需要根据客户端浏览器的不同显示不同的网页内容。
      策略模式通常通过定义一个抽象的基类,然后根据情况的不同创建不同的类继承这个基类。接下来,根据实际情况的判断,对这个基类采用不同的方式进行继承。
      以下代码实现了根据客户端浏览器的类型输出不同文字表达式的功能。这里,PHP 是通过 $_SERVER['HTTP_USER_AGENT'] 来获取用户端信息的。
    <?php
    //baseAgent类,抽象的基类
    abstract class baseAgent
    {
    abstract function PrintPage();
    }
    
    //ieAgent 类,用于客户端是 IE 时调用的类 
    class ieAgent extends baseAgent
    {
    function PrintPage()
    {
    return '当前浏览器是 IE!';
    }
    }
    
    //otherAgent 类,用于客户端不是 IE 时调用的类
    class otherAgent extends baseAgent
    {
    function PrintPage()
    {
    return '当前浏览器不是 IE!';
    }
    }
    
    //判断并创建不同的对象类型,对象名为 $currPage
    if(strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE'))
    {
    $currPage = new ieAgent();
    }
    else
    {
    $currPage = new otherAgent();
    } 
    //输出
    echo $currPage->PrintPage(); 
    ?> 
    


    上面程序在 IE 下的输出结果如下所示。
    当前浏览器是 IE!  单例模式(Singleton Pattern)
      单例模式指的是在应用程序的范围内只对指定的类创建一个实例。例如,对于一篇公共的文档可以允许多个用户同时阅读,但是仅允许一个用户编辑,否则会出现更新不同步的问题。
      单例模式包含的对象只有一个,就是单例本身。使用单例模式的类通常拥有一个私有构造耿耿数和一个私有克隆函数,确保用户无法通过创建对象或克隆的方式对其进行实例化。除些之外,该模式中还包含一个静态私有成员变量 $instance 与静态方法 getInstance。 getInstance 方法负责对其本身实例化,然后将这个对象存储在 $instance 静态成员变量中,以确保只有一个实例被创建。
      以下代码是一个简单的单例模式的例子,通过对单例属性 $switch 的设置实现了对开关状态的改变。
    <?php
    //单例模式的类 Lock
    class Lock 
    { 
    //静态属性 $instance
    static private $instance = NULL;
    //一个普通的成员属性
    private $switch = 0; 
    //getInstance 静态成员方法
    static function getInstance()
    {
    //如果对象实例还没有被创建,则创建一个新的实例
    if(self::$instance == NULL)
    {
    self::$instance = new Lock();
    }
    //返回对象实例
    return self::$instance;
    } 
    
    //空构造函数
    private function Lock() 
    {
    } 
    
    //空克隆成员函数
    private function __clone()
    {
    } 
    
    //设置$switch的函数,如果$switch为0则将其设置成1,否则将其设置成0
    function setLock()
    { 
    if($this->switch == 0)
    $this->switch = 1; 
    else
    $this->switch = 0;
    } 
    
    //获取$switch状态
    function getLock()
    {
    return $this->switch;
    }
    }
    
    //调用单例,设置$switch 
    Lock::getInstance()->setLock(); 
    
    //判断开关状态
    if(Lock::getInstance()->getLock() == 0) 
    echo '开关状态: 关';
    else
    echo '开关状态: 开';
    ?>  
    

     运行结果如下所示。
    开关状态:开  从上面的运行结果可以看出,第一次调用 Lock::getInstance()将$switch 设置成 1,第二次调用 Lock::getInstance()时获取的对象与第一次调用时相同。所以输出结果为 $switch 为 1 时的结果。
      工厂模式(Factory Pattern)
      工厂模式是指创建一个类似于工厂的类,通过对类中成员方法的调用返回不同类型的对象。例如,一个管理系统对于访问用户的权限设置是不同的。对于普通用户仅拥有一般的浏览权限,对于管理员拥有对数据的修改和删除权限,对于维护人员拥有访问用户的授权权即用等。
      工厂模式通常创建一个基类,根据对象类型的不同创建不同的扩展类,而工厂类就像生产零件一件,生产出类型不同的对象。在主程序中,通过对对象的调用实现不同的功能。
      以下代码实现了一个管理系统的例子。Factory 类就是一个工厂类,类中方法 Create 用于创建类型不同的对象得到不同的权限。
    <?php
    //抽象基类User
    abstract class User
    {
    protected $name = NULL;
    //构造函数
    function User($name)
    {
    $this->name = $name;
    } 
    
    //获取属性 $name
    function getName()
    {
    return $this->name;
    } 
    
    //是否具有浏览权限
    function ViewAccess()
    {
    return 'No';
    } 
    
    //是否具有编辑权限
    function EditAccess()
    {
    return 'No';
    }
    
    //是否具有删除权限
    function DeleteAccess()
    {
    return 'No';
    } 
    
    //是否具有用户管理权限
    function ManageAccess()
    {
    return 'No';
    } 
    
    }
    
    //普通用户
    class Client extends User 
    {
    function ViewAccess() 
    {
    return 'Yes';
    } 
    
    } 
    
    //管理员
    class Administrator extends User 
    {
    function ViewAccess()
    {
    return 'Yes';
    }
    
    function EditAccess()
    { 
    return 'Yes';
    } 
    
    function DeleteAccess()
    {
    return 'Yes';
    }
    }
    
    //维护人员
    class Supporter extends User
    {
    function ViewAccess()
    {
    return 'Yes';
    } 
    
    function EditAccess()
    {
    return 'Yes'; 
    }
    
    function DeleteAccess()
    {
    return 'Yes';
    } 
    
    function ManageAccess() 
    {
    return 'Yes';
    }
    } 
    
    //工厂类 
    class Factory
    {
    //静态成员属性
    private static $users = array('Simon'=>'Client', 'Elaine'=>'Administrator',
    'Bob'=>'Supporter'); 
    
    //创建对象的成员方法
    static function Create($name)
    {
    switch(self::$users[$name])
    {
    case 'Client':
    return new Client($name);
    case 'Administrator':
    return new Administrator($name);
    case 'Supporter':
    return new Supporter($name);
    }
    }
    }
    
    //一个存放用户名的数组 
    $users = array('Elaine', 'Simon', 'Bob'); 
    
    //对于每个用户分析其权限 
    foreach($users as $user)
    {
    $obj = Factory::Create($user);
    echo $obj->getName().' 的权限';
    echo '浏览:'.$obj->ViewAccess()."\n";
    echo '修改:'.$obj->EditAccess()."\n";
    echo '删除:'.$obj->DeleteAccess()."\n";
    echo '管理:'.$obj->ManageAccess()."\n";
    }
    ?> 
    

     
    需要注意的是工厂模式通常与策略模式结合使用,工厂模式通过对实例情况的判断正确的策略创建出合适的对象。



    该贴已经同步到 admin的微博
    分享到: QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    分享分享0 收藏收藏0 支持支持0 反对反对0 分享到人人 转发到微博
    [img=http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=fRUcHhYWGAQ9GxIFEBwUEVMeEhA]http://rescdn.qqmail.com/zh_CN/htmledition/images/function/qm_open/ico_mailme_02.png[/img]

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册 人人连接登陆

    晴云孤魂's Blog|就爱编程搜帖|手机版|Archiver|就爱编程论坛     

    GMT+8, 2025-7-2 13:12 , Processed in 0.139675 second(s), 26 queries .

    Powered by Discuz! X2

    © 2001-2011 Comsenz Inc.

    回顶部