PHP DIY 系列------框架篇:9. 設計模式

13sai發表於2020-02-25

框架的開發基本結束了,這一節我們來探討一下設計模式。


談設計模式,首先要來簡單聊聊物件導向。

物件導向

物件導向程式設計(Object-Oriented Programming, OOP)是一種程式設計範型,同時也是一種程式開發方法。它將物件作為程式的基本單元,將程式和資料封裝其中,以提高軟體的重用性、靈活性和可擴充套件性。它和麵向過程、函數語言程式設計被稱為程式語言中的三大正規化。

概念知識

  1. 物件導向的核心思想是物件、封裝、可重用性、可擴充套件性。
  2. 物件導向三要素:封裝、繼承和多型。
  3. 物件導向設計的五大原則:單一職責原則、介面隔離原則、開放封閉原則、替換原則、依賴倒置原則。

關於這些概念的更詳細解釋,我推薦大家閱讀《PHP核心技術與最佳實踐》這本書關於關於物件導向的部分。

設計模式

上述所述的物件導向知識,尤其是物件導向設計的五大原則,是諸多設計模式的基礎。

設計模式有很多,我們可以簡單列出來:

  1. 有強調例項化過程的建立型設計模式
  • 抽象工廠
  • 生成器
  • 工廠方法
  • 原型
  • 單例
  1. 又有組合物件和類構成更大結構的結構型設計模式
  • 介面卡模式
  • 橋接模式
  • 組合模式
  • 裝飾器模式
  • 外觀模式
  • 享元模式
  • 代理模式
  1. 還有行為型設計模式
  • 職責鏈模式
  • 命令模式
  • 直譯器模式
  • 迭代器模式
  • 中介者模式
  • 備忘錄模式
  • 觀察者模式
  • 狀態模式
  • 策略模式
  • 模板授權模式
  • 訪問者模式

說到這裡你有沒有蒙圈?

其實我們無需一下子去了解那麼多設計模式,在實際開發過程中我們可能也是混合使用設計模式的。我們不妨可以就框架裡用到的幾個典型的設計模式做一些分析。

單例模式

是否還記得我們使用Redis代替Session那一節,我們就用到了單例模式。

我們來簡化一下程式碼:

class RedisSession
{
    private $redis;

    private function getRedisInstance()
    {
        if (empty($this->redis)) {
            $redis = new \Redis();
            $redis->connect($this->_config['host'], $this->_config['port'], $this->_config['timeout']);
            if (!$this->_config['auth']) {
                $redis->auth($this->_config['auth']);
            }

            $this->redis = $redis;
        }
        return $this->redis;
    }
}

一般我們還會在類裡面加入一個魔術方法__clone,防止例項建立後被clone

單例模式有顯而易見的優點:提高可重用性,減少開銷。框架裡使用Redis時都可以使用此方法來獲取redis,也減少redis的連線數和多次連線時間。

策略模式

還記得依賴注入那一節麼,我們舉例的那個Travel就是一個很好的策略模式Demo:

interface Travel
{
    public function travelAlgorithm();
}

/**
 *具體策略類(ConcreteStrategy)
 *1:乘坐飛機
 */
class AirPlanelStrategy implements Travel
{
    public function travelAlgorithm()
    {
        echo"travelbyAirPlain\r\n";
    }
}

/**
 *具體策略類(ConcreteStrategy)
 *2:乘坐火車
 */
class TrainStrategy implements Travel
{
    public function travelAlgorithm()
    {
        echo"travelbyTrain\r\n";
    }
}

/**
 *
 *環境類(Context):
 *用一個ConcreteStrategy物件來配置。
 *維護一個對Travel物件的引用。可定義一個介面來讓Strategy訪問它的資料。
 *演算法解決類,以提供客戶選擇使用何種解決方案:
 */
class PersonContext
{
    private $strategy = null;

    public function __construct(Travel $travel)
    {
        $this->strategy=$travel;
    }

    /**
     *旅行
     */
    public function travel()
    {
        return$this->strategy->travelAlgorithm();
    }

}
// 乘坐火車旅行
$person = new PersonContext(new TrainStrategy());
$person->travel();

// 改乘飛機
$person =PersonContext(new AirPlanelStrategy());
$person->travel();

策略模式降低了程式碼耦合度,可以使得我們下層程式碼依賴上層,替換下層程式碼即可簡單實現功能的替換。

工廠方法

我們在路由解析建立控制器那裡使用了工廠方法,只不過與路由解析程式碼糅合在一起,我們簡化一下:

class Factory
{
    public function createController($controllerName)
    {
        $controllerName = rtrim($controllerName,'\\').'Controller';

        if (!class_exists($controllerName)) {
            throw new NotFoundException("未找到控制器");
        }

        return new $controllerName;
    }

    ···
}

工廠方法是很常見的一種設計模式,像Model經常能用到。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

分享開發知識,歡迎交流。qq957042781

相關文章