第三節 PHP設計模式(二)—工廠模式(Factor Pattern)

工廠模式(Factor Pattern),就是負責生成其他對象的類或方法,也叫工廠方法模式

抽象工廠模式( Abstract Factor Pattern),可簡單理解爲工廠模式的升級版

(一)爲什麼需要工廠模式

1,工廠模式可以將對象的生產從直接new 一個對象,改成通過調用一個工廠方法生產。這樣的封裝,代碼若需修改new的對象時,不需修改多處new語句,只需更改生產對象方法。

2,若所需實例化的對象可選擇來自不同的類,可省略if-else多層判斷,給工廠方法傳入對應的參數,利用多態性,實例化對應的類。

(二)工廠模式結構圖

1,工廠方法模式

2,抽象工廠模式

(三)簡單實現代碼

//工廠類
class Factor{   
    //生成對象方法
    static function createDB(){
        echo '我生產了一個DB實例';
        return new DB;
    }
}

//數據類
class DB{
    public function __construct(){
        echo __CLASS__.PHP_EOL;
    }
}

$db=Factor::createDB();

(四)實現一個運算器

abstract class Operation{
    abstract public function getVal($i, $j);
}
class Add extends Operation{
    public function getVal($i, $j)
    {
        return $i + $j;
    }
}
class Minus  extends Operation{
    public function getVal($i, $j)
    {
        return $i - $j;
    }
}
class Multiplied extends Operation{
    public function getVal($i, $j)
    {
        return $i * $j;
    }
}

class Divide extends Operation{
    public function getVal($i, $j)
    {
        if ($j == 0)
            throw new Exception("被除數不能爲0");
        return $i / $j;
    }
}
class CalcFactor{
    private static $operation;
    public static function createOperation(string $operation){
        switch ($operation){
            case "+":
                self::$operation = new Add();
                break;
            case "-":
                self::$operation = new Minus();
                break;
            case "*":
                self::$operation = new Multiplied();
                break;
            case "/":
                self::$operation = new Divide();
                break;
        }
        return self::$operation;
    }
}
$calc = CalcFactor::createOperation('/');
echo $calc->getVal(1,0);

缺點:每增加一個乘法運算,除了需要增加一個乘法運算類之外,還得去工廠生產方法裏面添加對應的case代碼,違反了開放-封閉原則。

解決方法:

(1):通過傳入指定類名

abstract class Operation{
    abstract public function getVal($i, $j);
}
class Add extends Operation{
    public function getVal($i, $j)
    {
        return $i + $j;
    }
}
class Minus  extends Operation{
    public function getVal($i, $j)
    {
        return $i - $j;
    }
}
class Multiplied extends Operation{
    public function getVal($i, $j)
    {
        return $i * $j;
    }
}

class Divide extends Operation{
    public function getVal($i, $j)
    {
        if ($j == 0)
            throw new Exception("被除數不能爲0");
        return $i / $j;
    }
}
class CalcFactor{
    public static function createOperation(string $operation){
                return new $operation;
    }
}
$calc = CalcFactor::createOperation("Divide");
echo $calc->getVal(1,1);

(2):通過抽象工廠模式

這裏順帶提一個問題:如果我係統還有個生產一個文本輸入器工廠,那麼那個工廠和這個計數器工廠又有什麼關係呢。

抽象高於實現

其實我們完全可以抽象出一個抽象工廠,然後將對應的對象生產交給子工廠實現。代碼如下:

// 抽象運算類
abstract class Operation{
    abstract public function getVal($i, $j);
}
// 加法類
class Add extends Operation{
    public function getVal($i, $j)
    {
        return $i + $j;
    }
}
// 減法類
class Minus  extends Operation{
    public function getVal($i, $j)
    {
        return $i - $j;
    }
}
// 乘法類
class Multiplied extends Operation{
    public function getVal($i, $j)
    {
        return $i * $j;
    }
}
// 除法類
class Divide extends Operation{
    public function getVal($i, $j) 
    {
        if ($j == 0)
            throw new Exception("被除數不能爲0");
        return $i / $j;
    }
}
// 抽象工廠類
abstract class Factor{
    abstract static function getInstance();
}
// 加法工廠類
class AddFactor extends Factor {
    public static function getInstance()
    {
        return new Add();
    }
}
// 減法工廠類
class MinusFactor extends Factor {
    public static function getInstance()
    {
        return new Minus();
    }
}
// 乘法工廠類
class MultipliedFactor extends Factor {
    public static function getInstance()
    {
        return new Multiplied();
    }
}
// 除法工廠類
class DivideFactor extends Factor {
    public static function getInstance()
    {
        return new Divide();
    }
}

$divide = DivideFactor::getInstance();
echo $divide->getVal(1,1);

第四節 PHP設計模式(三)—外觀模式(門面模式)(Facade Pattern)

參考資料:

https://design-patterns.readthedocs.io

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章