ThinkPHP 6.0 管道模式与中间件的实现分析

 

设计模式六大原则

  • 开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
  • 里氏替换原则:全部引用基类的地方必须能透明地使用其子类的对象.
  • 依赖倒置原则:高层模块不该该依赖低层模块,两者都应该依赖其抽象;抽象不该该依赖细节;细节应该依赖抽象。
  • 单一职责原则:不要存在多于一个致使类变动的缘由。通俗的说,即一个类只负责一项职责。
  • 接口隔离原则:客户端不该该依赖它不须要的接口;一个类对另外一个类的依赖应该创建在最小的接口上。
  • 迪米特法则:一个对象应该对其余对象保持最少的了解。

 

1.单例设计模式(Singleton)php

所谓单例模式,即在应用程序中最多只有该类的一个实例存在,一旦建立,就会一直存在于内存中!mysql

应用场景:laravel

单例设计模式常应用于数据库类设计,采用单例模式,只链接一次数据库,防止打开多个数据库链接。算法

一个单例类应具有如下特色:sql

单例类不能直接实例化建立,而是只能由类自己实例化。所以,要得到这样的限制效果,构造函数必须标记为private,从而防止类被实例化。shell

须要一个私有静态成员变量来保存类实例和公开一个能访问到实例的公开静态方法。数据库

在PHP中,为了防止他人对单例类实例克隆,一般还为其提供一个空的私有__clone()方法。编程

单例模式的例子:canvas

 1 <?php  2 
 3 /**  4 * Singleton of Database  5 */  
 6 class Database  7 {  8   // We need a static private variable to store a Database instance. 
 9   privatestatic $instance; 10 
11   // Mark as private to prevent it from being instanced. 
12   private function__construct() 13  { 14     // Do nothing. 
15  } 16 
17   private function__clone() 18  { 19     // Do nothing. 
20  } 21 
22   public static function getInstance() 23  { 24     if (!(self::$instance instanceof self)) { 25       self::$instance = new self(); 26  } 27 
28     return self::$instance; 29  } 30 } 31 
32 $a =Database::getInstance(); 33 $b =Database::getInstance(); 34 
35 // true 
36 var_dump($a === $b);

 

 

2.工厂设计模式设计模式

要是当操做类的参数变化时,只用改相应的工厂类就能够

工厂设计模式经常使用于根据输入参数的不一样或者应用程序配置的不一样来建立一种专门用来实例化并返回其对应的类的实例。

使用场景:使用方法 new实例化类,每次实例化只需调用工厂类中的方法实例化便可。

优势:因为一个类可能会在不少地方被实例化。当类名或参数发生变化时,工厂模式可简单快捷的在工厂类下的方法中 一次性修改,避免了一个个的去修改实例化的对象。

咱们举例子,假设矩形、圆都有一样的一个方法,那么咱们用基类提供的API来建立实例时,经过传参数来自动建立对应的类的实例,他们都有获取周长和面积的功能。

例子

 1 <?php  2 
 3 interface InterfaceShape  4 {  5  function getArea();  6  function getCircumference();  7 }  8 
 9 /** 10 * 矩形 11 */  
12 class Rectangle implements InterfaceShape 13 { 14   private $width; 15   private $height; 16 
17   public function __construct($width, $height) 18  { 19     $this->width = $width; 20     $this->height = $height; 21  } 22 
23   public function getArea() 24  { 25     return $this->width* $this->height; 26  } 27 
28   public function getCircumference() 29  { 30     return 2 * $this->width + 2 * $this->height; 31  } 32 } 33 
34 /** 35 * 圆形 36 */  
37 class Circle implements InterfaceShape 38 { 39   private $radius; 40 
41   function __construct($radius) 42  { 43     $this->radius = $radius; 44  } 45 
46 
47   public function getArea() 48  { 49     return M_PI * pow($this->radius, 2); 50  } 51 
52   public function getCircumference() 53  { 54     return 2 * M_PI * $this->radius; 55  } 56 } 57 
58 /** 59 * 形状工厂类 60 */  
61 class FactoryShape 62 { 63   public static function create() 64  { 65     switch (func_num_args()) { 66       case1:  
67       return newCircle(func_get_arg(0)); 68       case2:  
69       return newRectangle(func_get_arg(0), func_get_arg(1)); 70       default:  
71         # code... 
72         break; 73  } 74  } 75 } 76 
77 $rect =FactoryShape::create(5, 5); 78 // object(Rectangle)#1 (2) { ["width":"Rectangle":private]=> int(5) ["height":"Rectangle":private]=> int(5) } 
79 var_dump($rect); 80 echo "<br>"; 81 
82 // object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) } 
83 $circle =FactoryShape::create(4); 84 var_dump($circle); 85

 

 

3.观察者设计模式

观察者模式是挺常见的一种设计模式,使用得当会给程序带来很是大的便利,使用得不当,会给后来人一种难以维护的想法。

 

  • 多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提高,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货须要的能够免费分享给你们,须要的加群(点击→)677079770

使用场景:用户登陆,须要写日志,送积分,参与活动 等使用消息队列,把用户和日志,积分,活动之间解耦合

 

什么是观察者模式?一个对象经过提供方法容许另外一个对象即观察者 注册本身)使自己变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操做与可观察的对象无关。结果是对象能够相互对话,而没必要了解缘由。观察者模式是一种事件系统,意味着这一模式容许某个类观察另外一个类的状态,当被观察的类状态发生改变的时候,观察类能够收到通知而且作出相应的动做;观察者模式为您提供了避免组件之间紧密耦。看下面例子你就明白了!

 1 <?php  2 
 3 /* 
 4 观察者接口  5 */  
 6 interface InterfaceObserver  7 {  8   function onListen($sender, $args);  9   function getObserverName();  10 }  11 
 12 // 可被观察者接口 
 13 interface InterfaceObservable  14 {  15   function addObserver($observer);  16   function removeObserver($observer_name);  17 }  18 
 19 // 观察者抽象类 
 20 abstract class Observer implements InterfaceObserver  21 {  22   protected $observer_name;  23 
 24   function getObserverName()  25  {  26     return $this->observer_name;  27  }  28 
 29   function onListen($sender, $args)  30  {  31 
 32  }  33 }  34 
 35 // 可被观察类 
 36 abstract class Observable implements InterfaceObservable  37 {  38   protected $observers = array();  39 
 40   public function addObserver($observer)  41  {  42     if ($observerinstanceofInterfaceObserver)  43  {  44       $this->observers[] = $observer;  45  }  46  }  47 
 48   public function removeObserver($observer_name)  49  {  50     foreach ($this->observersas $index => $observer)  51  {  52       if ($observer->getObserverName() === $observer_name)  53  {  54         array_splice($this->observers, $index, 1);  55         return;  56  }  57  }  58  }  59 }  60 
 61 // 模拟一个能够被观察的类 
 62 class A extends Observable  63 {  64   public function addListener($listener)  65  {  66     foreach ($this->observersas $observer)  67  {  68       $observer->onListen($this, $listener);  69  }  70  }  71 }  72 
 73 // 模拟一个观察者类 
 74 class B extends Observer  75 {  76   protected $observer_name = 'B';  77 
 78   public function onListen($sender, $args)  79  {  80     var_dump($sender);  81     echo "<br>";  82     var_dump($args);  83     echo "<br>";  84  }  85 }  86 
 87 // 模拟另一个观察者类 
 88 class C extends Observer  89 {  90   protected $observer_name = 'C';  91 
 92   public function onListen($sender, $args)  93  {  94     var_dump($sender);  95     echo "<br>";  96     var_dump($args);  97     echo "<br>";  98  }  99 } 100 
101 $a = new A(); 102 // 注入观察者 
103 $a->addObserver(new B()); 104 $a->addObserver(new C()); 105 
106 // 能够看到观察到的信息 
107 $a->addListener('D'); 108 
109 // 移除观察者 
110 $a->removeObserver('B'); 111 
112 // 打印的信息: 113 // object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } } 114 // string(1) "D" 115 // object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } } 116 // string(1) "D" 

 

 

4.适配器模式

将一个类的接口转换成客户但愿的另外一个接口,适配器模式使得本来的因为接口不兼容而不能一块儿工做的那些类能够一块儿工做。
应用场景:老代码接口不适应新的接口需求,或者代码不少很乱不便于继续修改,或者使用第三方类库。

例如:php链接数据库的方法:mysql,,mysqli,pdo,能够用适配器统一

 1 //老的代码 
 2 
 3 class User {  4 
 5     private $name;  6 
 7     function __construct($name) {  8 
 9         $this->name = $name; 10 
11  } 12 
13     public function getName() { 14 
15         return $this->name; 16 
17  } 18 
19 } 20 //新代码,开放平台标准接口 
21 
22 interface UserInterface { 23 
24     function getUserName(); 25 
26 } 27 
28 class UserInfo implements UserInterface { 29 
30     protected $user; 31 
32     function __construct($user) { 33 
34         $this->user = $user; 35 
36  } 37 
38     public function getUserName() { 39 
40         return $this->user->getName(); 41 
42  } 43 
44 } 45 $olduser = new User('张三'); 46 
47 echo $olduser->getName()."n"; 48 
49 $newuser = new UserInfo($olduser); 50 
51 echo $newuser->getUserName()."n"; 52

 

5.策略模式

将一组特定的行为和算法封装成类,以适应某些特定的上下文环境。

使用场景:我的理解,策略模式是依赖注入,控制反转的基础

例如:一个电商网站系统,针对男性女性用户要各自跳转到不一样的商品类目,而且全部广告位展现不一样的广告

MaleUserStrategy.php

 1 <?php  2 
 3 namespace IMooc;  4 class MaleUserStrategy implements UserStrategy {  5     function showAd()  6  {  7         echo "IPhone6";  8  }  9 
10     function showCategory() 11  { 12         echo "电子产品"; 13  } 14 }

 

 

FemaleUserStrategy.php

 1 <?php  2 
 3 namespace IMooc;  4 
 5 class FemaleUserStrategy implements UserStrategy {  6     function showAd()  7  {  8         echo "2014新款女装";  9  } 10     function showCategory() 11  { 12         echo "女装"; 13  } 14 } 15

 

UserStrategy.php

 1 <?php  2 
 3 namespace IMooc;  4 
 5 interface UserStrategy {  6     function showAd();  7     function showCategory();  8 }  9  
10 
11 <?php 12 interface FlyBehavior{ 13     public function fly(); 14 } 15 
16 class FlyWithWings implements FlyBehavior{ 17     public function fly(){ 18         echo "Fly With Wings \n"; 19  } 20 } 21 
22 class FlyWithNo implements FlyBehavior{ 23     public function fly(){ 24         echo "Fly With No Wings \n"; 25  } 26 } 27 class Duck{ 28     private $_flyBehavior; 29     public function performFly(){ 30         $this->_flyBehavior->fly(); 31  } 32 
33     public function setFlyBehavior(FlyBehavior $behavior){ 34         $this->_flyBehavior = $behavior; 35  } 36 } 37 
38 class RubberDuck extends Duck{ 39 } 40 // Test Case 
41 $duck = new RubberDuck(); 42 
43 /* 想让鸭子用翅膀飞行 */  
44 $duck->setFlyBehavior(new FlyWithWings()); 45 $duck->performFly(); 46 
47 /* 想让鸭子不用翅膀飞行 */  
48 $duck->setFlyBehavior(new FlyWithNo()); 49 $duck->performFly();

 

 

6.装饰器模式
使用场景:当某一功能或方法draw,要知足不一样的功能需求时,可使用装饰器模式;实现方式:在方法的类中建addDecorator(添加装饰器),beforeDraw,afterDraw 3个新方法, 后2个分别放置在要修改的方法draw首尾.而后建立不一样的装器类(其中要包含相同的,beforeDraw,afterDraw方法)能过addDecorator添加进去,而后在beforeDraw,afterDraw中循环处理,与观察者模式使用有点类似
1.装饰器模式(Decorator),能够动态地添加修改类的功能
2.一个类提供了一项功能,若是要在修改并添加额外的功能,传统的编程模式,须要写一个子类继承它,并从新实现类的方法
3.使用装饰器模式,仅需在运行时添加一个装饰器对象便可实现,能够实现最大的灵活性
DrawDecorator.php

1 <?php 2 namespace IMooc; 3 
4 interface DrawDecorator 5 { 6     function beforeDraw(); 7     function afterDraw(); 8 }

 

Canvas.php

 1 <?php  2 namespace IMooc;  3 
 4 class Canvas  5 {  6     public $data;  7     protected $decorators = array();  8 
 9     //Decorator 
10     function init($width = 20, $height = 10) 11  { 12         $data = array(); 13         for($i = 0; $i < $height; $i++) 14  { 15             for($j = 0; $j < $width; $j++) 16  { 17                 $data[$i][$j] = '*'; 18  } 19  } 20         $this->data = $data; 21  } 22 
23     function addDecorator(DrawDecorator $decorator) 24  { 25         $this->decorators[] = $decorator; 26  } 27 
28     function beforeDraw() 29  { 30         foreach($this->decorators as $decorator) 31  { 32             $decorator->beforeDraw(); 33  } 34  } 35 
36     function afterDraw() 37  { 38         $decorators = array_reverse($this->decorators); 39         foreach($decorators as $decorator) 40  { 41             $decorator->afterDraw(); 42  } 43  } 44 
45     function draw() 46  { 47         $this->beforeDraw(); 48         foreach($this->data as $line) 49  { 50             foreach($line as $char) 51  { 52                 echo $char; 53  } 54             echo "<br />\n"; 55  } 56         $this->afterDraw(); 57  } 58 
59     function rect($a1, $a2, $b1, $b2) 60  { 61         foreach($this->data as $k1 => $line) 62  { 63             if ($k1 < $a1 or $k1 > $a2) continue; 64             foreach($line as $k2 => $char) 65  { 66                 if ($k2 < $b1 or $k2 > $b2) continue; 67                 $this->data[$k1][$k2] = ' '; 68  } 69  } 70  } 71 }

 

ColorDrawDecorator.php

 1 <?php  2 namespace IMooc;  3 
 4 class ColorDrawDecorator implements DrawDecorator  5 {  6     protected $color;  7     function __construct($color = 'red')  8  {  9         $this->color = $color; 10  } 11     function beforeDraw() 12  { 13         echo "<div style='color: {$this->color};'>"; 14  } 15     function afterDraw() 16  { 17         echo "</div>"; 18  } 19 }

 

index.php

 1 <?php  2 define('BASEDIR', __DIR__);  3 include BASEDIR.'/IMooc/Loader.php';  4 spl_autoload_register('\\IMooc\\Loader::autoload');  5 
 6 $canvas = new IMooc\Canvas();  7 $canvas->init();  8 $canvas->addDecorator(new \IMooc\ColorDrawDecorator('green'));  9 $canvas->rect(3,6,4,12); 10 $canvas->draw();
相关文章
相关标签/搜索