工廠模式分爲簡單工廠模式,工廠方法模式和抽象工廠模式,它們都屬於設計模式中的創建型模式。其主要功能都是幫助我們把對象的實例化部分抽取了出來,目的是降低系統中代碼耦合度,並且增強了系統的擴展性。本文對這三種模式進行了介紹並且分析它們之間的區別。
簡單工廠模式
簡單工廠模式最大的優點在於實現對象的創建和對象的使用分離,將對象的創建交給專門的工廠類負責,但是其最大的缺點在於工廠類不夠靈活,增加新的具體產品需要修改工廠類的判斷邏輯代碼,而且產品較多時,工廠方法代碼邏輯將會非常複雜。
<?php //簡單工廠方法 interface People { public function say(); } class Man implements People { public function say() { echo 'this is a man '; } } class Women implements People { public function say() { echo 'this is a women'; } } class SimpleFactory { public static function create($name) { if ($name == 'man') { return new Man(); } elseif ($name == 'women') { return new Women(); } } } //具體調用 $man = SimpleFactory::create('man'); $man->say(); $women = SimpleFactory::create('women'); $women->say();
簡單工廠模式最大的優點在於實現對象的創建和對象的使用分離,將對象的創建交給專門的工廠類負責,但是其最大的缺點在於工廠類不夠靈活,增加新的具體產品需要修改工廠類的判斷邏輯代碼,而且產品較多時,工廠方法代碼將會非常複雜。
工廠方法模式
此模式中,通過定義一個抽象的核心工廠類,並定義創建產品對象的接口,創建具體產品實例的工作延遲到其工廠子類去完成。這樣做的好處是核心類只關注工廠類的接口定義,而具體的產品實例交給具體的工廠子類去創建。當系統需要新增一個產品是,無需修改現有系統代碼,只需要添加一個具體產品類和其對應的工廠子類,使系統的擴展性變得很好,符合面向對象編程的開閉原則。體代碼如下:
<?php //工廠方法模式 interface People { public function say(); } class Man implements People { public function say() { echo 'this is a man'; } } class Women implements People { public function say() { echo 'this is a women'; } } //與簡單工廠模式相比。區別在於,此處將對象的創建抽象成一個接口 interface CreatePeople { public function create(); } class FactoryMan implements CreatePeople { public function create() { return new Man(); } } class FactoryWomen implements CreatePeople { public function create() { return new Women(); } } class Client { // 具體生產對象並執行對象方法測試 public function test() { $factory = new FactoryMan(); $man = $factory->create(); $man->say(); $factory = new FactoryWomen(); $man = $factory->create(); $man->say(); } } // 執行 $demo = new Client(); $demo->test();
工廠方法模式是簡單工廠模式的進一步抽象和推廣。由於使用了面向對象的多態性,工廠方法模式保持了簡單工廠模式的優點,而且克服了它的缺點。在工廠方法模式中,核心的工廠類不再負責所有產品的創建,而是將具體創建工作交給子類去做。這個核心類僅僅負責給出具體工廠必須實現的接口,而不負責產品類被實例化這種細節,這使得工廠方法模式可以允許系統在不修改工廠角色的情況下引進新產品。
抽象工廠模式
提供一個創建一系列相關或相互依賴對象的接口,而無須指定它們具體的類。抽象工廠模式又稱爲Kit模式,屬於對象創建型模式。
此模式是對工廠方法模式的進一步擴展。在工廠方法模式中,一個具體的工廠負責生產一類具體的產品,即一對一的關係,但是,如果需要一個具體的工廠生產多種產品對象,那麼就需要用到抽象工廠模式了。
<?php interface TV{ public function open(); public function watch(); } class HaierTv implements TV { public function open() { echo "Open Haier TV <br>"; } public function watch() { echo "I'm watching TV <br>"; } } interface PC{ public function work(); public function play(); } class LenovoPc implements PC { public function work() { echo "I'm working on a Lenovo computer <br>"; } public function play() { echo "Lenovo computers can be used to play games <br>"; } } abstract class Factory{ abstract public static function createPc(); abstract public static function createTv(); } class ProductFactory extends Factory { public static function createTV() { return new HaierTv(); } public static function createPc() { return new LenovoPc(); } } $newTv = ProductFactory::createTV(); $newTv->open(); $newTv->watch(); $newPc = ProductFactory::createPc(); $newPc->work(); $newPc->play();
在上面的Factory抽象類中,定義了兩個抽象方法,這兩個抽象方法分別用來生產不同的產品(即由不同類實例化的對象)。
工廠方法模式和抽象工廠模式對比
通過以上代碼:我們來對比一下工廠方法模式和抽象工廠模式:
- 工廠方法模式中
當我需要多生產一種新的產品,比如factoryKid這個產品,我需要專門再設一個factoryKid的工廠,即添加如下代碼:
class Kid implements People{ public function say() { echo 'this is a kid'; } } class FactoryKid implements CreatePeople { public function create() { return new Kid(); } }
- 抽象工廠模式中
同樣當我需要多生產一種新的產品,比如生產一個iphone,此時我需要修改工廠父類裏的接口,並且在具體工廠類ProductFactory這個工廠裏增加一條createPhone生產線(即類裏面的方法),所需添加的代碼如下:
interface Phone{ public function work(); public function sms(); } class IPhone implements Phone { public function work() { echo "I'm iphone <br>"; } public function sms() { echo "this is an iphone <br>"; } } //在原來的抽象工廠類中添加方法聲明 abstract class Factory{ abstract public static function createPc(); abstract public static function createTv(); abstract public static function createPhone(); } //在原來的工廠類裏添加一個方法 class ProductFactory extends Factory { public static function createTV() { return new HaierTv(); } public static function createPc() { return new LenovoPc(); } public static function createPhone() { return new IPhone(); } }
從上面的分析可以看出,要生產一個新的產品,抽象工廠模式並不比工廠方法模式更爲便捷,那麼抽象工廠模式的好處在哪呢?它優點就是在於是增加固定類型產品的不同具體工廠比較方便,比如我要增加一個生產同樣類型產品的具體工廠Product2Factory,那麼就再建一個Product2Factory類繼承Factory就可以了。
最後的最後,總結一下工廠方法模式和抽象工廠模式的核心區別
- 工廠方法模式利用繼承,抽象工廠模式利用組合
- 工廠方法模式產生一個對象,抽象工廠模式產生一族對象
- 工廠方法模式利用子類創造對象,抽象工廠模式利用接口的實現創造對象