定義: 簡單工廠模式:將調用者和創建者分離,實現解耦,調用者直接向工廠請求,通過工廠去選擇需要實例化的對象,用一個單獨的類來做這個創建實例的過程。 代碼實例: 問題:假設一個關於個人事務管理的項目中有許多類型的對象,其中一個是 Appointment 對象,現在需要通過一種稱為 BloggsCal ...
定義:
簡單工廠模式:將調用者和創建者分離,實現解耦,調用者直接向工廠請求,通過工廠去選擇需要實例化的對象,用一個單獨的類來做這個創建實例的過程。
代碼實例:
問題:假設一個關於個人事務管理的項目中有許多類型的對象,其中一個是 Appointment 對象,現在需要通過一種稱為 BloggsCal 的格式進行預約數據的交互。後面可能還需要處理更多的數據格式,比如 MegaCal 格式。
1、創建一個抽象類 ApptEncoder
/** * 抽象類 * Class ApptEncoder */ abstract class ApptEncoder { abstract public function encode(); }
2、創建 BloggsCal 格式處理類
/** * BloggsCal 格式處理類 * Class BloggsApptEncoder */ class BloggsApptEncoder extends ApptEncoder { public function encode() { // TODO: Implement encode() method. return "Appointment data encoded in BloggsCal format\n"; } }
3、創建 MegaCal 格式處理類
/** * MegaCal 格式處理類 * Class MegaApptEncoder */ class MegaApptEncoder extends ApptEncoder { public function encode() { // TODO: Implement encode() method. return "Appointment data encoded in MegaCal format\n"; } }
4、創建工廠類 CommsManager
/** * 工廠類 * Class CommsManager */ class CommsManager { const BLOGGS = 1; const MEGA = 2; private $model; /** * CommsManager constructor. * @param $model */ public function __construct($model) { $this->model = $model; } /** * 通過工廠去選擇需要實例化的對象 */ public function getApptEncoder() { switch ($this->model) { case (self::BLOGGS): return new BloggsApptEncoder(); default: return new MegaApptEncoder(); } } }
5、調用:
$man = new CommsManager(CommsManager::BLOGGS); print $man->getApptEncoder()->encode(); $man = new CommsManager(CommsManager::MEGA); print $man->getApptEncoder()->encode();
6、結果:
Appointment data encoded in BloggsCal format
Appointment data encoded in MegaCal format
如果後面需要新增一種格式處理,則需要新增一個相應的格式處理類,再到工廠類中增加相應的實例化調用就可以了。
總結:
簡單工廠模式的最大優點在於工廠類中包含了必要的邏輯判斷,根據客戶端的選擇條件動態實例化相關的類,對於客戶端來說,去除了與具體產品的依賴。
但剛纔也說了,如果新增一種格式處理,是要修改工廠類的。這就等於說,我們不但對擴展開放了,對修改也開放了,因此違背了“開放-封閉原則”。這時可以使用工廠方法模式。