上回說到,簡單工廠不屬于GoF的二十三種設計模式,這回可就來真家伙了,大名頂頂的工廠方法模式前來報道!
GoF類圖解釋
工廠方法模式對比簡單工廠來說,最核心的一點,其實就是將實作推遲到子類,怎么理解呢?我們可以將上回的簡單工廠當做父類,然后有一堆子類去繼承它,createProduct()這個方法在父類中也變成一個抽象方法,然后所有的子類去實作這個方法,不再需要用switch去判斷,子類直接回傳一個實體化的物件即可,
GoF定義:定義一個用于創建物件的介面,讓子類決定實體化哪一個類,Factory Method使一個類的實體化推遲到其子類,
GoF類圖

- 類圖中的Product為產品
- 類圖中的Creator為創建者
- 創建者父類有一個抽象的FactoryMethod()工廠方法
- 所有創建者子類需要實作這個工廠方法,回傳對應的具體產品
- 創建者父類可以有一個AnOperation()操作方法,直接回傳product,可以使用FactoryMethod()去回傳,這樣外部只需要統一呼叫AnOperation()
代碼實作
首先是商品相關的介面和實作類,和簡單工廠的類似:
// 商品介面
interface Product{
function show() : void;
}
// 商品實作類A
class ConcreteProductA implements Product{
public function show() : void{
echo "I'm A.\n";
}
}
接下來是創建者的抽象和實作類:
// 創建者抽象類
abstract class Creator{
// 抽象工廠方法
abstract protected function FactoryMethod() : Product;
// 操作方法
public function AnOperation() : Product{
return $this->FactoryMethod();
}
}
// 創建者實作類A
class ConcreteCreatorA extends Creator{
// 實作操作方法
protected function FactoryMethod() : Product{
return new ConcreteProductA();
}
}
這里和簡單工廠就有了本質的區別,我們去掉了惡心的switch,讓每個具體的實作類來進行商品物件的創建,沒錯,單一和封閉,每個單獨的創建者子類只在工廠方法中和一個商品有耦合,有沒有其他商品和其他的工廠來跟客戶合作過這個子類完全不知道,
同樣還是拿手機來比喻:我是一個賣手機的批發商(客戶Client,業務方),我需要一批手機(產品ProductA),于是我去讓富X康(工廠Creator)來幫我生產,我跟富士康說明了需求,富士康說好的,讓我的衡陽工廠(ConcreteCreatorA)來搞定,不需要總廠上,你這小單子,灑灑水啦,然后過了一陣我又需要另一種型號的手機(產品ProductB),富士康看了看后又讓鄭州富士康(ConcreteCreatorB)來幫我生產,反正不管怎么樣,他們總是給了我對應的手機,而且鄭州工廠并不知道衡陽工廠生產過什么或者有沒有跟我合作過,這一切只有我和總工廠知道,
完整代碼:工廠方法模式
實體
場景:光說不練假把式,把上回的短信發送改造改造,我們依然還是使用上回的那幾個短信發送商,畢竟大家已經很熟悉了嘛,不過以后要更換也說不定,商場如戰場,大家還是利益為先,這樣的話,我們通過工廠方法模式來進行解耦,就可以方便的添加修改短信提供商咯,
短信發送類圖

代碼實作
<?php
interface Message {
public function send(string $msg);
}
class AliYunMessage implements Message{
public function send(string $msg){
// 呼叫介面,發送短信
// xxxxx
return '阿里云短信(原阿里大魚)發送成功!短信內容:' . $msg;
}
}
class BaiduYunMessage implements Message{
public function send(string $msg){
// 呼叫介面,發送短信
// xxxxx
return '百度SMS短信發送成功!短信內容:' . $msg;
}
}
class JiguangMessage implements Message{
public function send(string $msg){
// 呼叫介面,發送短信
// xxxxx
return '極光短信發送成功!短信內容:' . $msg;
}
}
abstract class MessageFactory{
abstract protected function factoryMethod();
public function getMessage(){
return $this->factoryMethod();
}
}
class AliYunFactory extends MessageFactory{
protected function factoryMethod(){
return new AliYunMessage();
}
}
class BaiduYunFactory extends MessageFactory{
protected function factoryMethod(){
return new BaiduYunMessage();
}
}
class JiguangFactory extends MessageFactory{
protected function factoryMethod(){
return new JiguangMessage();
}
}
// 當前業務需要使用百度云
$factory = new BaiduYunFactory();
$message = $factory->getMessage();
echo $message->send('您有新的短訊息,請查收');
完整原始碼:短信發送工廠方法
說明
- 和類圖完全一致,基本不需要什么說明了吧,注意工廠方法模式的特點,實作推遲到了子類!!
- 業務呼叫的時候需要耦合一個Factory子類,確實是這樣,如果你想一個統一的出口來呼叫,請在外面加一層簡單工廠就好啦,這就當成一道思考題吧
- 不拘泥于目前的形式,可以不用抽象類,直接用一個介面來定義工廠方法,摒棄掉getMessage()方法,外部直接呼叫公開的模板方法(factoryMethod)即可
下期看點
抽象工廠模式,老大哥即將登場,壓軸的總是最強悍的,讓我們看看老大哥的本事!
關注公眾號:【硬核專案經理】獲取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、專案管理學習資料
知乎、公眾號、抖音、頭條搜索【硬核專案經理】
B站ID:482780532
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/233382.html
標籤:PHP
上一篇:mysql入門必備
