簡介
工廠模式屬于創建型模式,可以分為三種:簡單工廠、工廠模式、抽象工廠,
通俗講就是用于如何優雅的創建物件而設計,當開發者不知道建什么物件,或者創建方式過于復雜的時候去使用(比如引入一個大composer專案或大型sdk,有些時候確實不知道需要使用那些物件,此時就需要參考官方檔案,通過包里或sdk里提供的工廠方法,傳入指定引數去生成指定物件,比如easyWechat專案,),適用于具有服務端和呼叫端的場景,既能優化呼叫端的使用體感,也能隱藏服務端創建物件的細節,
簡單工廠
作用
幫忙創建物件(核心方法可以使用靜態方法,稱之為靜態工廠),
適用場景
- 當不知道創建什么物件的時候去使用
- 創建物件過于復雜的時候去使用,
優點
簡單工廠是工廠模式中創建物件最簡單的方式,通俗容易理解,
缺點
當要生產物件的模塊發生了需求變更,此時要被實體化的類可能會增加或者減少,此時就需要改工廠模式的核心代碼,違背了開閉原則,
代碼
class Keyboard{
public function run() {
return '我能打字';
}
}
class Mouse {
public function run() {
return '我能控制游標';
}
}
class Factory {
public static function build($key) {
if($key == 'mouse') {
return new Mouse();
} else if ($key == 'keyboard') {
return new Keyboard();
}
}
}
//----------呼叫端----------
$res = Factory::build('mouse')->run();
/*
筆者認為,簡單工廠可以簡化為以下寫法
但是這會有三個缺陷:
1. 能否做到類名寫法一致?不一定能做到
2. 缺少白名單機制,不安全,指不定new那個類,特別是這個引數守用戶傳參影響的場景,不過這個可以讓需要實體化的類實作一個介面,工廠方法添加typehint (型別約束)限制,
3. 如果修改白名單,又違背了開閉原則,
*/
class Factory {
public static function build($class) {
return ucfirst($class);
}
}
工廠模式
作用
解決了簡單工廠模式中違背開閉原則的問題,
適用場景
- 并解決了簡單工廠模式下,一旦類發生變化,就需要修改核心模塊的作用,遵循開閉原則,
- 產品層變化較大的的場景
優點
- 將創建物件的程序推遲的子類去實作,職責清晰,比較符合開閉原則,
- 并解決了簡單工廠模式下,一旦類發生變化,就需要修改核心模塊的作,
缺點
額外增加設計復雜度,每增加一個類,就需要增加一個子工廠,增加了系統抽象性,
代碼
interface Usb {
public function run();
}
class Keyboard implements USb {
public function run() {
return '我能打字';
}
}
class Mouse implements USb {
public function run() {
return '我能控制游標';
}
}
interFace Factory {
public static function build();
}
class KeyboardFactory implements Factory {
public static function build() :Keyboard {
return new Keyboard();
}
}
class MouseFactory implements Factory {
public static function build() :Mouse {
return new Mouse();
}
}
//----------呼叫端----------
$res = MouseFactory::build()->run();
抽象工廠
作用
- 抽象工廠相比于工廠模式,可以創建一堆互有關聯物件,
- 抽象工廠的實作由4部分構成:抽象工廠,具體工廠,抽象產品,具體產品,
適用場景
物件創建程序復雜,并且類與類之間有關聯的時候,
優點
抽象工廠可以用一個類的不同方法回傳不同物件,(工廠模式一個子類生產一個物件,抽象工廠可以生產出多個物件),替代系統中存在大量的工廠類,
缺點
會產生較大的變動,需要添加指定的方法去維護抽象工廠的完整性,
代碼
interface Talk {
public function say();
}
class EnglishTalk implements Talk {
public function say() {
return 'I can speak English';
}
}
class ChineseTalk implements Talk {
public function say() {
return '我會說中文';
}
}
interface Write {
public function writeWord();
}
class EnglishWrite implements Write {
public function writeWord() {
return 'I can write English words';
}
}
class ChineseWrite implements Write {
public function writeWord() {
return '我會寫漢字';
}
}
interface Factory {
public static function buildSay();
public static function buildWriteWord();
}
class EnglishFactory implements Factory {
public static function buildSay() :EnglishTalk {
return new EnglishTalk();
}
public static function buildWriteWord() :EnglishWrite {
return new EnglishWrite();
}
}
class ChineseFactory implements Factory {
public static function buildSay() :ChineseTalk {
return new ChineseTalk();
}
public static function buildWriteWord():ChineseWrite {
return new ChineseWrite();
}
}
//----------呼叫端----------
//中國人對應會說漢語,或寫漢字,這就是有關聯,
$chinese_say = ChineseFactory::buildSay()->say();
$chinese_write_word = ChineseFactory::buildWriteWord()->writeWord();
三者對比
| 簡單工廠 | 工廠模式 | 抽象工廠 | |
|---|---|---|---|
| 實作難度 | 相對簡單 | 相對復雜 | 相對復雜 |
| 實作細節 | 通過方法生產物件(不需要子類) | 通過子類方法去生產物件 | 通過子類方法去生產有關聯的物件 |
| 優點 | 實作簡單 | 解決了簡單工廠違背開閉原則的問題 | 可以制造一堆有關聯的物件,減少工廠模式下工廠子類的數量 |
| 缺點 | 違背開閉原則,不適用修改產品 | 更加抽象,類數量增加,不方便維護 | 更加抽象,類數量增加,不方便維護 |
| 適用場景 | 簡單場景,類之間無關聯且不經常變動 | 需要實體化的產品容易有變動 | 類之間有關聯,且不經常變動 |
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/519023.html
標籤:PHP
