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();
相關文章
相關標籤/搜索