常用設計模式詳解


設計模式的作用:一方面將變化的東西封裝起來,另一方面將眾多的類抽象開防止類過多

1、簡單工廠模式

不同條件下創建不同實例

 

2、抽象工廠模式

簡單工廠模式有個問題,每添加一次新的類都要修改方法,不符合面向對象的開閉原則(對類的增加開放,對類的修改閉合)

抽象工廠模式便解決了這一問題,每次添加新的類就行了。

 

 

3、單例模式

保證一個類僅有一個實例

<?php
namespace Test;

class Database
{
   //私有化內部實例化的對象
    private static $instance = null;
   //私有化構造方法,禁止外部實例化
    private function __construct(){}
    //私有化__clone,防止被克隆
    private function __clone(){}
    // 公有靜態實例方法
    public static function getInstance(){
       if(empty(self::$instance)){
              self::$instance=new Test();
           }
           return self::$instance;
       }
    }

$obj1=Test::getInstance();
$obj2=Test::getInstance();
echo $obj1==$obj2?1:0;

 

 

4、觀察者模式

一對多的依賴關系,在觀察目標類里有一個 ArrayList 存放觀察者們。當觀察目標對象的狀態發生改變,所有依賴於它的觀察者都將得到通知,使這些觀察者能夠自動更新(即使用推送方式) 

主題提供注冊和通知的接口,觀察者提供自身操作的接口。(這些觀察者擁有一個同一個接口。)觀察者利用主題的接口向主題注冊,而主題利用觀察者接口通知觀察者。耦合度相當之低。

如何實現觀察者注冊?通過前面的注冊者模式很容易給我們提供思路,把這些對象加到一棵注冊樹上就好了嘛。如何通知?這就更簡單了,對注冊樹進行遍歷,讓每個對象實現其接口提供的操作。

 

<?php
// 主題接口
interface Subject{
    public function register(Observer $observer);
    public function notify();
}
// 觀察者接口
interface Observer{
    public function watch();
}
// 主題
class Action implements Subject{
     public $_observers=array();
     public function register(Observer $observer){
         $this->_observers[]=$observer;
     }

     public function notify(){
         foreach ($this->_observers as $observer) {
             $observer->watch();
         }

     }
 }

// 觀察者
class Cat implements Observer{
     public function watch(){
         echo "Cat watches TV<hr/>";
     }
 } 
 class Dog implements Observer{
     public function watch(){
         echo "Dog watches TV<hr/>";
     }
 } 
 class People implements Observer{
     public function watch(){
         echo "People watches TV<hr/>";
     }
 }



// 應用實例
$action=new Action();
$action->register(new Cat());
$action->register(new People());
$action->register(new Dog());
$action->notify();

 

 

5、責任鏈模式

 攔截的類都實現統一接口,每個接收者都包含對下一個接收者的引用。將這些對象連接成一條鏈,並且沿着這條鏈傳遞請求,直到有對象處理它為止。

<?php   
  
//申請Model  
class Request  
{  
    //數量  
    public $num;  
    //申請類型  
    public $requestType;  
    //申請內容  
    public $requestContent;  
}  
  
//抽象管理者  
abstract class Manager  
{  
    protected $name;  
    //管理者上級  
    protected $manager;  
    public function __construct($_name)  
    {  
        $this->name = $_name;  
    }  
  
    //設置管理者上級  
    public function SetHeader(Manager $_mana)  
    {  
        $this->manager = $_mana;  
    }  
  
    //申請請求  
    abstract public function Apply(Request $_req);  
  
}  
  
//經理  
class CommonManager extends Manager  
{  
    public function __construct($_name)  
    {  
        parent::__construct($_name);  
    }  
    public function Apply(Request $_req)  
    {  
        if($_req->requestType=="請假" && $_req->num<=2)  
        {  
            echo "{$this->name}:{$_req->requestContent} 數量{$_req->num}被批准。<br/>";  
        }  
        else  
        {  
            if(isset($this->manager))  
            {  
                $this->manager->Apply($_req);  
            }  
        }  
  
    }  
}  
  
//總監  
class MajorDomo extends Manager  
{  
    public function __construct($_name)  
    {  
        parent::__construct($_name);  
    }  
  
    public function Apply(Request $_req)  
    {  
        if ($_req->requestType == "請假" && $_req->num <= 5)  
        {  
            echo "{$this->name}:{$_req->requestContent} 數量{$_req->num}被批准。<br/>";  
        }  
        else  
        {  
            if (isset($this->manager))  
            {  
                $this->manager->Apply($_req);  
            }  
        }  
  
    }  
}  
  
  
//總經理  
class GeneralManager extends Manager  
{  
    public function __construct($_name)  
    {  
        parent::__construct($_name);  
    }  
  
    public function Apply(Request $_req)  
    {  
        if ($_req->requestType == "請假")  
        {  
            echo "{$this->name}:{$_req->requestContent} 數量{$_req->num}被批准。<br/>";  
        }  
        else if($_req->requestType=="加薪" && $_req->num <= 500)  
        {  
            echo "{$this->name}:{$_req->requestContent} 數量{$_req->num}被批准。<br/>";  
        }  
        else if($_req->requestType=="加薪" && $_req->num>500)  
        {  
            echo "{$this->name}:{$_req->requestContent} 數量{$_req->num}再說吧。<br/>";  
        }  
    }  
}    

調用:

header("Content-Type:text/html;charset=utf-8");  
//--------------------職責鏈模式----------------------  
require_once "./Responsibility/Responsibility.php";  
$jingli = new CommonManager("李經理");  
$zongjian = new MajorDomo("郭總監");  
$zongjingli = new GeneralManager("孫總");  
  
//設置直接上級  
$jingli->SetHeader($zongjian);  
$zongjian->SetHeader($zongjingli);  
  
//申請  
$req1 = new Request();  
$req1->requestType = "請假";  
$req1->requestContent = "小菜請假!";  
$req1->num = 1;  
$jingli->Apply($req1);  
  
$req2 = new Request();  
$req2->requestType = "請假";  
$req2->requestContent = "小菜請假!";  
$req2->num = 4;  
$jingli->Apply($req2);  
  
$req3 = new Request();  
$req3->requestType = "加薪";  
$req3->requestContent = "小菜請求加薪!";  
$req3->num = 500;  
$jingli->Apply($req3);  
  
$req4 = new Request();  
$req4->requestType = "加薪";  
$req4->requestContent = "小菜請求加薪!";  
$req4->num = 1000;  
$jingli->Apply($req4);  

  

6、策略模式

策略對象依賴注入到context對象,context對象根據它的策略改變而改變它的相關行為(可通過調用內部的策略對象實現相應的具體策略行為) 

<?php
header('Content-Type:text/html;charset=utf-8');
/**
 * 策略模式演示代碼
 *
 * 為了更好地突出“策略”,我們這里以出行為例演示,日常出行大概分為以下幾種工具:自駕車,公交車,地鐵,火車,飛機,輪船
 *
 * 下面一起看代碼,領會何為策略模式
 */

/**
 * Interface Travel 抽象策略角色
 * 約定具體方法
 */
interface Travel
{
    public function go();
}

/**
 * Class selfDriving 具體策略角色
 * 自駕車
 */
class bySelfDriving implements Travel
{
    public function go()
    {
        echo '我自己開着車出去玩<br>';
    }
}

/**
 * Class byBus具體策略角色
 * 乘公交
 */
class byBus implements Travel {
    public function go()
    {
        echo '我乘公交出去玩<br>';
    }
}

/**
 * Class byMetro 具體策略角色
 * 乘地鐵
 */
class byMetro implements Travel
{
    public function go()
    {
        echo '我乘地鐵出去玩<br>';
    }
}

/**
 * Class byTrain 具體策略角色
 * 乘火車
 */
class byTrain implements Travel
{
    public function go()
    {
        echo '我乘火車出去玩<br>';
    }
}

/**
 * Class byAirplane 具體策略角色
 * 乘飛機
 */
class byAirplane implements Travel
{
    public function go()
    {
        echo '我乘飛機出去玩<br>';
    }
}

/**
 * Class bySteamship 具體策略角色
 * 乘輪船
 */
class bySteamship implements Travel
{
    public function go()
    {
        echo '我乘輪船出去玩<br>';
    }
}

/**
 * Class Mine 環境角色
 */
class Mine{
    private $_strategy;
    private $_isChange = false;

    /**
     * 構造方法
     * 此處使用到了依賴注入和類型約束的概念,詳情請參考
     * 1.聊一聊PHP的依賴注入(DI) 和 控制反轉(IoC)
     * @link https://segmentfault.com/a/1190000007209266
     * 2.淺談PHP的類型約束
     * @link https://segmentfault.com/a/1190000007226476
     *
     * @param Travel $travel
     */
    public function __construct(Travel $travel)
    {
        $this->_strategy = $travel;
    }

    /**
     * 改變出行方式
     *
     * @param Travel $travel
     */
    public function change(Travel $travel)
    {
        $this->_strategy = $travel;
        $this->_isChange = true;
    }

    public function goTravel()
    {
        if ($this->_isChange) {
            echo '現在改變主意,';
            $this->_strategy->go();
        } else {
            $this->_strategy->go();
        }

    }
}

/**
 * 客戶端使用
 */
$strategy = new Mine(new byBus());
// 乘公交
$strategy->goTravel();
// 乘地鐵
$strategy->change(new byMetro());
$strategy->goTravel();
// 自駕車
$strategy->change(new bySelfDriving());
$strategy->goTravel();

// 其他根據具體應用選擇實現

運行結果

我乘公交出去玩
現在改變主意,我乘地鐵出去玩
現在改變主意,我自己開着車出去玩

 

7、裝飾器模式

保持接口,增強性能:修飾類繼承被修飾對象的抽象父類,依賴被修飾對象的實例(被修飾對象依賴注入),以實現接口擴展

基類傳入基本的數據,可通過后面的類進行加工處理,自主組合

 

 

 8、適配器模式

使得原本由於接口不兼容而不能一起工作的那些類可以一起工作

 

 9、橋接模式

兩個維度獨立變化,依賴方式實現抽象與實現分離:需要一個作為橋接的接口/抽象類,多個角度的實現類依賴注入到抽象類,使它們在抽象層建立一個關聯關系

類的組合完成業務邏輯

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM