浅谈php设计模式

来源:互联网 发布:旋风磁力数据接口 编辑:程序博客网 时间:2024/06/05 11:48

PHP一共有五个设计模式,分别对应为:

1、命令链模式

命令模式(Command)是封装一个通用操作的机制。它相当于程序中的:回调(callback)。(就是调用一个方法,方法实例化)

回调通常使用一个函数指针或数据结构如PHP中的字符串和数组实现,

[php] view plain copy
  1. /**   
  2.  * The Command abstraction.   
  3.  * In this case the implementation must return a result,   
  4.  * sometimes it only has side effects.   
  5.  */   
  6. interface Validator    
  7. {    
  8.     /**   
  9.      * The method could have any parameters.   
  10.      * @param mixed   
  11.      * @return boolean   
  12.      */   
  13.     public function isValid($value);    
  14. }    
  15.    
  16. /**   
  17.  * ConcreteCommand.   
  18.  */   
  19. class MoreThanZeroValidator implements Validator    
  20. {    
  21.     public function isValid($value)    
  22.     {    
  23.         return $value > 0;    
  24.     }    
  25. }    
  26.    
  27. /**   
  28.  * ConcreteCommand.   
  29.  */   
  30. class EvenValidator implements Validator    
  31. {    
  32.     public function isValid($value)    
  33.     {    
  34.         return $value % 2 == 0;    
  35.     }    
  36. }    
  37.    
  38. /**   
  39.  * The Invoker. An implementation could store more than one   
  40.  * Validator if needed.   
  41.  */   
  42. class ArrayProcessor    
  43. {    
  44.     protected $_rule;    
  45.    
  46.     public function __construct (Validator $rule)    
  47.     {    
  48.         $this->_rule = $rule;    
  49.     }    
  50.    
  51.     public function process(array $numbers)    
  52.     {    
  53.         foreach ($numbers as $n) {    
  54.             if ($this->_rule->IsValid($n)) {    
  55.                 echo $n"\n";    
  56.             }    
  57.         }    
  58.     }    
  59. }    
  60.    
  61. // Client code    
  62. $processor = new ArrayProcessor(new EvenValidator());  //<span style="font-family: 宋体;">new EvenValidator() 返回 </span><span style="font-family: 宋体;">EvenValidator实例化的对象 </span><span style="font-family: 宋体;">  
  63. </span>$processor->process(array(1, 20, 18, 5, 0, 31, 42));   

Command是在一个方法调用之上的抽象,它吸收了所有面向对象的好处:合成、继承和处理。




2、策略模式

定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

封装:把行为用接口封装起来,我们可以把那些经常变化的部分,从当前的类中单独取出来,用接口进行单独的封装。
互相替换:我们封装好了接口,通过指定不同的接口实现类进行算法的变化。

//如下
我们创建了一个超人类(duck)
还有一个基类接口类(FlyBehavior),定义了里面的一个fly()方法
建立了另外两个类FlyWithWings 和FlyWithNo 继承了FlyBehavior 类 ,FlyWithWings 和 FlyWithNo 分别重构了自己的 fly() 方法,
仿我们调用超人类(duck)时 通过调用setFlyBehavior()方法时就可以通过传不同的类,返回不同的对象.虽然他们后面调用的方法名一样.但是对象不同.
所以他们调用了不同的方法(相当于)

[php] view plain copy
  1. <?php  
  2. interface FlyBehavior{  
  3.     public function fly();  
  4. }  
  5.    
  6. class FlyWithWings implements FlyBehavior{  
  7.     public function fly(){  
  8.         echo "Fly With Wings \n";  
  9.     }  
  10. }  
  11.    
  12. class FlyWithNo implements FlyBehavior{  
  13.     public function fly(){  
  14.         echo "Fly With No Wings \n";  
  15.     }  
  16. }  
  17. class Duck{  
  18.     private $_flyBehavior;  
  19.     public function performFly(){  
  20.         $this->_flyBehavior->fly();  
  21.     }  
  22.    
  23.     public function setFlyBehavior(FlyBehavior $behavior){  
  24.         $this->_flyBehavior = $behavior;//返回传的那个类  
  25.     }  
  26. }  
  27.    
  28. class RubberDuck extends Duck{  
  29. }  
  30. // Test Case  
  31. $duck = new RubberDuck();  
  32.    
  33. /*  想让鸭子用翅膀飞行 */  
  34. $duck->setFlyBehavior(new FlyWithWings());  
  35. $duck->performFly();              
  36.    
  37. /*  想让鸭子不用翅膀飞行 */  
  38. $duck->setFlyBehavior(new FlyWithNo());  
  39. $duck->performFly();  


3、工厂模式
只要是可以根据不同的参数生成不同的类实例,那么就符合工厂模式的设计思想。

[php] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <?php   
  2.     //吃  
  3.     class Eat(){  
  4.         public static function eatNoodles(){  
  5.         return '吃面';  
  6.     }  
  7.     }  
  8.       
  9.     //喝  
  10.     class Drink(){  
  11.     public static function drinkWater(){  
  12.         return '喝水';  
  13.     }      
  14.     }    
  15.     //吃喝拉撒  
  16.     class EatAndDrink(){  
  17.     public static function createObj($type){  
  18.         switch($type){  
  19.             case 'eat':  
  20.             return new Eat();  
  21.             case 'drink':  
  22.             return new Drink();           
  23.         }  
  24.     }     
  25.     }  
  26.       
  27.     $obj = EatAndDrink::createObj('eat');  
  28.     var_dump($obj);  
  29.     
  30.       
  31.     $obj = EatAndDrink::createObj('drink');  
  32.     var_dump($obj);  
  33. ?>  
  34. 就如上面的代码一样,有一个单独的eat类和drink类,还有一个吃喝拉撒类,调用EatAndDrink类里面的createObj的方法来返回不同的实例化的对象  


4、单元素模式(单例模式)

      单元素模式(单例模式)特点:

单例模式按字面来看就是某一个类只有一个实例,这样做的好处还是很大的,比如说数据库的连接,我们只需要实例化一次,

不需要每次都去new了,这样极大的降低了资源的耗费。(如MySQL连接)


单例类至少拥有以下三种公共元素:

    必须拥有一个构造函数,并且必须被标记为private。
    拥有一个保存类的实例的静态成员变量。
    拥有一个访问这个实例的公共的静态方法

[php] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <?php  
  2.       
  3.     class Mysql{  
  4.         //该属性用来保存实例  
  5.         private static $conn;  
  6.         //构造函数为private,防止创建对象  
  7.         private function __construct(){  
  8.             $this->conn = mysql_connect('localhost','root','');  
  9.         }  
  10.         //创建一个用来实例化对象的方法  
  11.         public static function getInstance(){  
  12.             if(!(self::$conn instanceof self)){  
  13.                 self::$conn = new self;  
  14.             }  
  15.             return self::$conn;  
  16.         }  
  17.         //防止对象被复制  
  18.         public function __clone(){  
  19.             trigger_error('Clone is not allowed !');  
  20.         }  
  21.           
  22.     }  
  23.     //只能这样取得实例,不能new 和 clone  
  24.     $mysql = Mysql::getInstance();  
  25. ?>  

5、观察者模式

观察者模式定义对象的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新!

 主题和观察者都使用接口:观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。这样可以让两者之间运作正常,又同时具有松耦合的优点! ——针对接口编程,不针对实现编程!

[php] view plain copy
  1. <?php  
  2. /** 
  3.  * 观察者模式 
  4.  * @author: Mac 
  5.  * @date: 2012/02/22 
  6.  */  
  7.    
  8.    
  9. class Paper{ /* 主题    */  
  10.     private $_observers = array();  
  11.    
  12.     public function register($sub){ /*  注册观察者 */  
  13.         $this->_observers[] = $sub;  
  14.     }  
  15.    
  16.        
  17.     public function trigger(){  /*  外部统一访问    */  
  18.         if(!empty($this->_observers)){  
  19.             foreach($this->_observers as $observer){  
  20.                 $observer->update();  
  21.             }  
  22.         }  
  23.     }  
  24. }  
  25.    
  26. /** 
  27.  * 观察者要实现的接口 
  28.  */  
  29. interface Observerable{  
  30.     public function update();  
  31. }  
  32.    
  33. class Subscriber implements Observerable{  
  34.     public function update(){  
  35.         echo "Callback\n";  
  36.     }  
  37. }  
  38.    
  39.   
  40. 下面是测试代码  
  41.   
  42. /*  测试    */  
  43. $paper = new Paper();  
  44. $paper->register(new Subscriber());  
  45. //$paper->register(new Subscriber1());  
  46. //$paper->register(new Subscriber2());  
  47. $paper->trigger(); 
0 0