您好,登錄后才能下訂單哦!
什么是簡單工廠、工廠方法、抽象工廠?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
簡單工廠模式
基本上每個人手機里都有一款音樂播放器,目前流行的播放器有:QQ音樂、酷狗音樂、酷狗音樂、網易云音樂、天天動聽等。下面是一段關于播放音樂的代碼:
if ($type == 'QQ') { $player = new QQPlayer(); } else if ($type == 'Wy') { $player = new WyPlayer(); } else if ($type == 'KG') { $player = new KGPlayer(); } else { $palyer = null; } $player->on(); // 打開播放器 $player->choiceMusic('我不配'); // 選擇歌曲 $player->play(); // 開始播放
為了時代碼的邏輯更加清晰、可讀性更好,我們要善于把功能獨立的代碼塊封裝成函數。按照這個設計思路,我們可以將其中的條件分支抽離出來,單獨放在一個類中的方法中。這個類,我們就可以叫做簡單工廠模式。
簡單工廠模式的定義:一個類可以根據不同的參數來獲取不同的實例,一般這些被創建的實例都具有相同的父類。
靜態工廠模式:一般的,我們將簡單工廠模式中的用于創建不同實例的方法設置為靜態方法,避免創建多個相同實例。
下面我們用簡單工廠模式改寫上面的代碼
class MusicPlayerFactory { public static function create ($type) { if ($type == 'QQ') { $player = new QQPlayer(); } else if ($type == 'Wy') { $player = new WyPlayer(); } else if ($type == 'KG') { $player = new KGPlayer(); } else { $player = null; } return $player; } } // 業務代碼修改如下 $player = MusicPlayerFactory:create('QQ'); $player->on(); // 打開播放器 $player->choiceMusic('我不配'); // 選擇歌曲 $player->play(); // 開始播放
對于上面的簡單工廠模式,如果我們需要添加新的音樂播放器,就一定會修改MusicPlayerFactory的create方法,這有點不符合“開閉原則”。對于這種條件分支不是很多,另外類的創建也非常的簡單,使用簡單工廠模式是完全可以的。如果非要將if分支邏輯去掉,使他符合“開閉原則”,那么就可以使用工廠方法來實現。對于工廠方法,也不是一定比簡單工廠模式要好,雖然它的擴展性比較好,但是犧牲了可讀性。
工廠方法模式
定義:在工廠方法模式中,工廠父類負責定義創建產品對象的公共接口,而工廠子類則負責生成具體的產品對象,這樣做的目的是將產品類的實例化操作延遲到工廠子類中完成,即通過工廠子類來確定究竟應該實例化哪一個具體產品類。
現在我們用“多態”來消除掉上面簡單工廠模式的if分支結構。實現的代碼如下所示:
interface IMusicPlayerFactory { static function create (); } class QQPlayerFactory implements IMusicPlayerFactory { public static function create () { return new QQPlayer(); } } class WyPlayerFactory implements IMusicPlayerFactory { public static function create () { return new WyPlayer(); } } class KGPlayerFactory implements IMusicPlayerFactory { public static function create () { return new KGPlayer(); } } // 業務代碼修改如下 if ($type == 'QQ') { $player = QQPlayerFactory::create(); } else if ($type == 'Wy') { $player = WyPlayerFactory::create(); } else if ($type == 'KG') { $player = KGPlayerFactory::create(); } else { throw new \Exception('...'); } $player->on(); // 打開播放器 $player->choiceMusic('我不配'); // 選擇歌曲 $player->play(); // 開始播放
可以看到,問題又回到了原點,業務代碼里又出現了if條件分支結構。那么怎么去解決該問題呢?
我們可以為工廠類再創建一個簡單工廠,用來創建工廠類對象。新的簡單工廠代碼如下:
class MusicPlayerFactoryMap { const Players = [ 'QQ' => 'QQPlayerFactory', 'Wy' => 'WyPlayerFactory', 'KG' => 'KGPlayerFactory' ]; public static function getPlayerFactory (string $type) { if (empty($type)) { return null; } return (self::Players[$type])::create(); } } // 業務代碼修改如下 $palyer = MusicPlayerFactoryMap::getPlayerFactory('QQ') $player->on(); // 打開播放器 $player->choiceMusic('我不配'); // 選擇歌曲 $player->play(); // 開始播放
可以看到,使用了工廠模式,結構變的比之前復雜的多。如果來的創建實例過程復制,我們才會推薦使用工廠方法模式。
抽象工廠模式
抽象工廠模式使用場景比較特殊,用的比較少。在工廠方法模式中,具體工廠負責生產具體的產品,每一個工廠對應一個具體產品。但有時候,我們需要一個工廠可以創建多個產品對象,而不是一個單一的產品。
我們用一個例子來看看:對象電腦廠是負責生產電腦來出售的。我們知道,電腦是由主機、鍵盤、顯示器以及鼠標組成的,目前對象電腦城只生產3種電腦,低配、中配和高配的,不同配置的電腦使用的主機品牌、顯示器品牌等都是不同的。
主機目前有:麒麟主機、雷霆主機、冬日主機
鍵盤目前有:雷柏、羅技、雷蛇
顯示器目前有:aoc、hkc、BenQ
鼠標目前有:羅技、靈蛇、方正
頂配版電腦由麒麟主機、雷柏鍵盤、aoc顯示器、羅技鼠標組成,中配由……。
關于主機的代碼如下:
interface Host { static function createHost (); } class DrHost implements Host { public static function createHost() { echo '創建冬日主機' . PHP_EOL; } } class QlHost implements Host { public static function createHost() { echo '創建麒麟主機' . PHP_EOL; } } class LtHost implements Host { public static function createHost() { echo '創建雷霆主機' . PHP_EOL; } }
類似的,去創建鍵盤、顯示器、鼠標,代碼這里就不貼了。
現在,我們定義一個創建電腦的接口。
interface ComputerFactory { static function createHost (); static function createKeyboard (); static function createMonitor (); static function createMouse (); }
然后完成三個具體工廠用于創建低配、中配以及高配版電腦。
class GreatComputerFactory implements ComputerFactory { public static function createHost() { QlHost::createHost(); } public static function createKeyboard() { LbKeyboard::createKeyboard(); } public static function createMonitor() { AocMonitor::createMonitor(); } public static function createMouse() { LjMouse::createMouse(); } } class GoodComputerFactory implements ComputerFactory { public static function createHost() { LtHost::createHost(); } public static function createKeyboard() { LjKeyboard::createKeyboard(); } public static function createMonitor() { HkcMonitor::createMonitor(); } public static function createMouse() { LsMouse::createMouse(); } } class NormalComputerFactory implements ComputerFactory { public static function createHost() { DrHost::createHost(); } public static function createKeyboard() { LsKeyboard::createKeyboard(); } public static function createMonitor() { BenqMonitor::createMonitor(); } public static function createMouse() { FzMouse::createMouse(); } }
現在可以來創建具體的電腦了
class GreatComputer { public function __construct() { echo '高配電腦' . PHP_EOL; GreatComputerFactory::createHost(); GreatComputerFactory::createKeyboard(); GreatComputerFactory::createMonitor(); GreatComputerFactory::createMouse(); } } class GoodComputer { public function __construct() { echo '中配電腦' . PHP_EOL; GoodComputerFactory::createHost(); GoodComputerFactory::createKeyboard(); GoodComputerFactory::createMonitor(); GoodComputerFactory::createMouse(); } } class NormalComputer { public function __construct() { echo '低配電腦' . PHP_EOL; NormalComputerFactory::createHost(); NormalComputerFactory::createKeyboard(); NormalComputerFactory::createMonitor(); NormalComputerFactory::createMouse(); } }
看完上述內容,你們掌握什么是簡單工廠、工廠方法、抽象工廠的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。