php设计魔术

97 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情

PHP设计模式

常见的设计模式: 策略模式 工厂模式 单例模式 注册模式 

单例模式

  • 又称职责模式,通俗地说是实例化出来的对象是唯一的
  • 单例类不能再其它类中直接实例化,只能被其自身实例化
  • 它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用
  • 特点
    • 必须拥有一个构造函数,并且必须被标记为private
    • 拥有一个保存类的实例的静态成员变量
    • 它们拥有一个访问这个实例的公共的静态方法
    • 只能有一个实例.
    • 必须自行创建这个实例.
    • 必须给其他对象提供这一实例.
  • eg
        class Single 
        {
            // 声明一个私有的实例变量
            private $name;
            // 声明私有构造方法为了防止外部代码使用new来创建对象
            private function __construct()
            {
            
            }
    
            // 声明一个静态变量(保存在类中唯一的一个实例)
            static public $instance;
            // 声明一个getinstance()静态方法,用于检测是否有实例对象
            static public function getinstance()
            {
                if(!self::$instance) {
                    self::$instance = new self();
                }
                return self::$instance;
            }
    
            public function setname($n)
            { 
                $this->name = $n; 
            }
    
            public function getname()
            { 
                return $this->name; 
            }
        }
    
        $oa = Single::getinstance();
        $ob = Single::getinstance();
        $oa->setname('hello world');
        $ob->setname('good morning');
        echo $oa->getname();//good morning
        echo $ob->getname();//good morning
    

工厂模式

  • 工厂方法代替new操作的一种模式
  • 好处
    • 如果想要更改所实例化的类名等,则只需更改该工厂方法内容即可,不需逐一寻找代码中具体实例化的地方(new处)修改了
    • 为系统结构提供灵活的动态扩展机制,减少了耦合
  • eg
        // 创建一个基本的工厂类
        class Factory 
        {
            // 创建一个返回对象实例的静态方法
            static public function fac($id)
            {
                if (1 == $id) {
                    return new A();
                } elseif (2 == $id) {
                    return new B();
                } elseif (3 == $id) {
                    return new C();
                } else {
                    return new D();
                }   
            }
        }
    
        // 创建一个接口
        interface FetchName 
        {
            public function getname();
        }
    
        class A implements FetchName
        {
            private $name = "AAAAA";
            public function getname()
            { 
                return $this->name; 
            }
        }
    
        class C implements FetchName
        {
            private $name = "CCCCC";
            public function getname()
            { 
                return $this->name; 
            }
        }
    
        class B implements FetchName
        {
            private $name = "BBBBB";
            public function getname()
            { 
                return $this->name; 
            }
        }
    
        class D implements FetchName
        {
            private $name = "DDDDD";
            public function getname()
            { 
                return $this->name; 
            }
        }
    
        // 调用工厂类中的方法
        $o = Factory::fac(6);
        if ($o instanceof FetchName) {
            echo $o->getname();//DDDDD
        }
    
        $p=Factory::fac(3);
        echo $p->getname();//CCCCC
    

策略模式

  • 对一组算法的封装.动态的选择需要的算法并使用
  • 三个角色
    • 抽象策略角色
    • 具体策略角色
    • 环境角色(对抽象策略角色的引用)
  • eg
        // 抽象策略类
        abstract class baseAgent 
        { 
            abstract function PrintPage();
        }
    
        // 用于客户端是IE时调用的类(环境角色)
        class ieAgent extends baseAgent 
        {
            function PrintPage() 
            {
                return 'IE';
            }
        }
    
        // 用于客户端不是IE时调用的类(环境角色)
        class otherAgent extends baseAgent 
        {
            function PrintPage() 
            {
                return 'not IE';
            }
        }
    
        // 具体策略角色
        class Browser 
        { 
            public function call($object)  
            {
                return $object->PrintPage();
            }
        }
    
        $bro = new Browser();
        echo $bro->call ( new ieAgent() );
    

注册模式

  • 解决全局共享和交换对象
  • 已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可
  • eg
        class Register
        {
            protected static $objects;
    
            // 将对象注册到全局的树上
            function set($alias, $object)
            {
                // 将对象放到树上
                self::$objects[$alias] = $object;
            }
            
            // 获取某个注册到树上的对象
            static function get($name)
            {
                return self::$objects[$name];
            }
    
            // 移除某个注册到树上的对象
            function _unset($alias)
          {
                unset(self::$objects[$alias]);
            }
        }