這一章講的是簡單工廠模式和工廠方法模式的比較。
????先是說,小菜有個(gè)同學(xué)薛磊風(fēng)(學(xué)雷鋒),平時(shí)默默無聞,一天不幸出了車禍,然后同學(xué)們就去醫(yī)院看望他,才知道他三年如一日地為一位孤寡老人做好事,然后他現(xiàn)在住院了嘛,就拜托小菜他們替他照顧一下老人家。
????坦白講呢,如果是我的話,我做不到這么偉大,我只想照顧好自己的家人就夠了。
????然后呢,小菜和大鳥說了這個(gè)事情,他們就開始談?wù)撛O(shè)計(jì)模式了,今天討論的是簡單工廠和工廠方法模式。
????簡單工廠就是第一章講的那個(gè),在工廠類中有switch來生成對應(yīng)的運(yùn)算子類,而工廠方法模式呢,是在抽象工廠下面又?jǐn)U展了對應(yīng)的加減乘除四個(gè)工廠,有什么區(qū)別呢?
????在簡單工廠中,如果要新增運(yùn)算,那么就要修改工廠類,增加switch的分支,這就違背了開-閉原則,而工廠方法中,新增運(yùn)算是新增對應(yīng)的運(yùn)算工廠類,這樣不違背開閉原則。
????簡單工廠模式最大的優(yōu)點(diǎn)是工廠類中包含了必要的邏輯判斷,根據(jù)客戶端的選擇條件動(dòng)態(tài)的實(shí)例化相關(guān)的類,對于客戶端來說,去除了與具體產(chǎn)品相關(guān)的依賴。比如計(jì)算器例子中,客戶端不用管該用哪個(gè)類的實(shí)例,只需要把運(yùn)算符傳給工廠就行。但是不可避免的違背了開閉原則,因?yàn)樾略鲞\(yùn)算符勢必需要修改工廠類。
????下面來重點(diǎn)理解一下工廠方法模式:定義一個(gè)用于創(chuàng)建對象的接口,讓子類決定實(shí)例化哪個(gè)子類,把一個(gè)類的實(shí)例化延遲到子類中。
????工廠方法模式實(shí)現(xiàn)時(shí),客戶端需要決定實(shí)例化哪一個(gè)工廠來實(shí)現(xiàn)運(yùn)算類,選擇判斷的問題還是存在的,也就是說,工廠方法模式把簡單工廠的內(nèi)部判斷邏輯移到了客戶端中,你想要增加功能,本來是改工廠類,現(xiàn)在是修改客戶端。
回到這一章的故事上來,用代碼來表示幫助老人這個(gè)故事:
/***
* 雷鋒抽象類
*/
public abstract class LeiFeng {
// 掃地
abstract void sweep();
// 洗衣服
abstract void wash();
// 買米
abstract void buyRice();
}
現(xiàn)在三個(gè)學(xué)生去做好事,學(xué)生類Student繼承LeiFent,在客戶端中這樣調(diào)用:
public static void main(String[] args) {
LeiFeng student1 = new Student();
LeiFeng student2 = new Student();
LeiFeng student3 = new Student();
student1.sweep();
student2.wash();
student3.buyRice();
}
如果此時(shí)這三個(gè)不是學(xué)生,而是志愿者,那么就需要修改每個(gè)new Student()的地方,改成new Volunteer(),
如果用簡單工廠來描述,就是:
switch
"學(xué)生" :
new Student();
break;
"志愿者":
new Volunteer();
break;
每個(gè)實(shí)例化學(xué)生的地方,都要寫Factory.createLeiFeng("學(xué)生"),如果需要改成志愿者,那么每個(gè)地方都要修改;
而如果用工廠方法模式來描述這個(gè)例子,就是:
先創(chuàng)建StudentFactory和VolunteerFactory兩個(gè)工廠類,繼承LeiFengFactory,在客戶端中:
LeiFengFactory leiFengFactory = new StudentFactory();
LeiFeng leiFeng1 = leiFengFactory.createLeiFeng();
LeiFeng leiFeng2 = leiFengFactory.createLeiFeng();
LeiFeng leiFeng3 = leiFengFactory.createLeiFeng();
leiFeng1.buyRice();
leiFeng2.sweep();
leiFeng3.wash();
這樣,如果要改成志愿者做好事,那么只需要修改new StudentFactory()為new VolunteerFactory(),只需要改這一個(gè)地方就行。
工廠方法模式比簡單工廠要高明一點(diǎn),它既封裝了創(chuàng)建對象的過程,又克服了開閉原則,缺點(diǎn)是每加一個(gè)產(chǎn)品,就要對應(yīng)增加一個(gè)工廠類。 -- “反射,可以解決這個(gè)問題?!?/p>