PHP設計模式(2):工廠模式(Factory)

什麼是工廠模式

就是負責生成其他對象的類或方法

為什麼需要工廠模式
  1. 工廠模式可以將對象的生產從直接new 一個對象,改成通過調用一個工廠方法生產。這樣的封裝,代碼若需修改new的對象時,不需修改多處new語句,只需更改生產對象方法。
  2. 若所需實例化的對象可選擇來自不同的類,可省略if-else多層判斷,給工廠方法傳入對應的參數,利用多態性,實例化對應的類。
工廠模式結構圖


PHP設計模式(2):工廠模式(Factory)

簡單工廠模式


PHP設計模式(2):工廠模式(Factory)

抽象工廠模式

簡單代碼實現
<code>//工廠類
class Factor
{
// 生成對象方法
public static function createDB()
{
echo '我生產了一個DB實例';
return new DB;
}
}

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

$db = Factor::createDB();/<code>
實現一個運算器
<code>// 抽象運算類
abstract class Operation
{
abstract public function getVal($i, $j); // 抽象方法不能包含方法體
}
// 加法類
class OperationAdd extends Operation
{
public function getVal($i, $j)
{
return $i + $j;
}
}
// 減法類
class OperationSub extends Operation

{
public function getVal($i, $j)
{
return $i - $j;
}
}

//計數器工廠
class CounterFactor
{
private static $operation;
// 工廠生產特定類對象方法
public static function createOperation(string $operation)
{
switch ($operation) {
case '+': self::$operation = new OperationAdd;
break;
case '-': self::$operation = new OperationSub;
break;
}
return self::$operation;
}
}

$counter = CounterFactor::createOperation('+');
echo $counter->getVal(1, 2);
/<code>

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

解決方法(1):通過傳入指定類名
<code>// 計算器工廠
class CounterFactor
{
// 工廠生產特定類對象方法
public static function createOperation(string $operation)
{
return new $operation;
}

}
class OperationMul extends Operation
{
public function getVal($i, $j)
{
return $i * $j;
}
}
$counter = CounterFactor::createOperation('OperationMul');
/<code>
解決方法(2):通過抽象工廠模式

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

抽象高於實現

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

<code>// 抽象運算類
abstract class Operation
{
abstract public function getVal($i, $j); //抽象方法不能包含方法體
}
// 加法類
class OperationAdd extends Operation
{
public function getVal($i, $j)
{
return $i + $j;
}
}
// 乘法類
class OperationMul extends Operation
{
public function getVal($i, $j){
return $i * $j;

}
}
// 抽象工廠類
abstract class Factor
{
abstract static function getInstance();
}
// 加法器生產工廠
class AddFactor extends Factor
{
// 工廠生產特定類對象方法
public static function getInstance()
{
return new OperationAdd;
}
}
// 減法器生產工廠
class MulFactor extends Factor
{
public static function getInstance()
{
return new OperationMul;
}
}
// 文本輸入器生產工廠
class TextFactor extends Factor
{
public static function getInstance() {}
}
$mul = MulFactor::getInstance();
echo $mul->getVal(1, 2);/<code>


分享到:


相關文章: