定義一個用於建立對象的接口(抽象工廠類),讓子類決定實例化哪個類,工廠方法使得一個類的實例化延遲到其子類(抽象工廠類的子類)。php
工廠方法模式是簡單工廠模式的進一步抽象和推廣。在簡單工廠模式中,當新增一個類時都須要改動一次工廠類方法。而工廠方法模式中將一個類的實例化延續到抽象工廠的子類,使得新增一個類時只需建立一個對應的工廠類便可。所以工廠方法模式符合開閉原則。code
工廠方法模式更適合須要建立一系列實例的場景。工廠方法模式的特色是將簡單工廠模式的內部邏輯判斷移到了客戶端代碼中進行,也就是工廠方法模式是經過在客戶端決定實例化哪個具體工廠來建立相應的實例。對象
如這樣一個場景:幾個大學生學雷鋒作好事,幫一個老人家作家務活。分別用簡單工廠模式和工廠方法模式實現以下:blog
//簡單工廠模式 $leiFengA = SimpleFactory->CreateLeiFeng('學雷鋒的大學生'); $leiFengA->BuyRice(); $leiFengB = SimpleFactory->CreateLeiFeng('學雷鋒的大學生'); $leiFengB->Sweep(); $leiFengC = SimpleFactory->CreateLeiFeng('學雷鋒的大學生'); $leiFengC->Wash();
//工廠方法模式 $factory = new UndergraduateFactory(); $leiFengA = factory->CreateLeiFeng(); $leiFengA->BuyRice(); $leiFengB = factory->CreateLeiFeng(); $leiFengB->Sweep(); $leiFengC = factory->CreateLeiFeng(); $leiFengC->Wash();
若是這時有個需求,因爲大學生們畢業了各奔東西,無法再幫老人家作家務活了,須要由社區志願者來代替他們作好事。那麼修改上面客戶端代碼時,簡單工廠模式須要將全部的「學雷鋒的大學生」替換成社區志願者。而工廠方法模式中,只須要將UndergraduateFactory()(學雷鋒的大學生工廠)換成VolunteerFactory()(社區志願者工廠)。接口
//雷鋒類 class LeiFeng { public function sweep() { echo '掃地'; } public function wash() { echo '洗衣'; } public function buyRice() { echo '買米'; } }
//大學生 class Undergraduate extends LeiFeng { }
//社區志願者 class Volunteer extends LeiFeng { }
//雷鋒工廠類 abstract class LeiFengFactory { abstract public function createLeiFeng(); }
//學雷鋒的大學生工廠類 class UndergraduateFactory extends LeiFengFactory { public function createLeiFeng() { return new Undergraduate(); } }
//社區志願者工廠類 class VolunteerFactory extends LeiFengFactory { public function createLeiFeng() { return new Volunteer(); } }
//客戶端 $factory = new UndergraduateFactory(); $leiFeng = $factory->createLeiFeng(); $leiFeng->sweep();