概述
一直不清楚這三個(gè)工廠模式的區(qū)別,于是看了幾篇博客,想著把看到的和自己的理解梳理一下,于是有了這篇博客。我認(rèn)為學(xué)習(xí)設(shè)計(jì)模式盡量結(jié)合平時(shí)的編碼習(xí)慣以及一些優(yōu)秀框架的源碼學(xué)習(xí),前者讓我們關(guān)注設(shè)計(jì)模式如何改進(jìn)編碼風(fēng)格,例如寫(xiě)web項(xiàng)目一般分service,serviceImpl,然后實(shí)例的引用是service,而不是serviceImpl,這是利用了oop的多態(tài),后者很考驗(yàn)框架設(shè)計(jì)人員能力,spring自從設(shè)計(jì)以來(lái)都是在基礎(chǔ)上不斷擴(kuò)展,這正是由于spring運(yùn)用了大量設(shè)計(jì)模式,在剛開(kāi)始功能簡(jiǎn)單和模塊少的時(shí)候就寫(xiě)了大量看似冗余的代碼,但這些代碼為spring提供了極大擴(kuò)展性和易讀性。
抽象工廠

一個(gè)產(chǎn)品族可以理解為同一個(gè)廠家的系列產(chǎn)品,一個(gè)產(chǎn)品等級(jí)可以理解為不同廠家的相同產(chǎn)品。
現(xiàn)在情況是這樣的,進(jìn)貨商要購(gòu)進(jìn)一批手機(jī)和電腦, 為了方便測(cè)試購(gòu)進(jìn)設(shè)備的功能,于是進(jìn)貨商提供了描述手機(jī)基本功能的抽象類(lèi)和描述電腦基本功能的抽象類(lèi)
public abstract class Phone {
public abstract void start(); // 手機(jī)開(kāi)機(jī)測(cè)試
}
public abstract class Computer {
public abstract void start(); // 電腦開(kāi)機(jī)測(cè)試
}
進(jìn)貨商又嫌購(gòu)貨渠道太麻煩,于是又提供了一個(gè)抽象類(lèi)用于生產(chǎn)設(shè)備,華為和小米只要實(shí)現(xiàn)具體細(xì)節(jié),進(jìn)貨商只需要調(diào)用方法即可,這個(gè)抽象類(lèi)就是抽象工廠
public abstract class DeviceFactory {
public abstract Phone createPhone();
public abstract Computer createComputer();
}
小米為了給進(jìn)貨商供貨,于是有了產(chǎn)品具體實(shí)現(xiàn)和工廠具體實(shí)現(xiàn)
public class MIPhone extends Phone {
@Override
public void start() {
System.out.println("成功開(kāi)機(jī)");
}
}
public class MIComputer extends Computer {
@Override
public void start() {
System.out.println("成功開(kāi)機(jī)");
}
}
public class MIDeviceFactory extends DeviceFactory {
@Override
public Phone createPhone() {
return new MIPhone();
}
@Override
public Computer createComputer() {
return new MIComputer();
}
}
華為同樣
public class HUAWEIPhone extends Phone {
@Override
public void start() {
System.out.println("成功開(kāi)機(jī)");
}
}
public class HUAWEIComputer extends Computer {
@Override
public void start() {
System.out.println("成功開(kāi)機(jī)");
}
}
public class HUAWEIDeviceFactory extends DeviceFactory {
@Override
public Phone createPhone() {
return new HUAWEIPhone();
}
@Override
public Computer createComputer() {
return new HUAWEIComputer();
}
}
進(jìn)貨商需要購(gòu)買(mǎi)小米設(shè)備,只需
DeviceFactory factory = new MIDeviceFactory();
Phone phone = factory.createPhone();
phone.start(); // 測(cè)試是否可以開(kāi)機(jī)
Computer computer = factory.createComputer();
computer.start();
小米設(shè)備夠了,切換成購(gòu)買(mǎi)華為設(shè)備,切換的編碼成本非常小
DeviceFactory factory = new HUAWEIDeviceFactory();
Phone phone = factory.createPhone();
phone.start(); // 測(cè)試是否可以開(kāi)機(jī)
Computer computer = factory.createComputer();
computer.start();
抽象工廠模式的四種角色:
- AbstractFactory:抽象工廠,聲明了創(chuàng)建各個(gè)產(chǎn)品的方法
- ConcreteFactory:具體工廠,實(shí)現(xiàn)抽象工廠中聲明的方法
- AbstractProduct:抽象產(chǎn)品,為各個(gè)產(chǎn)品聲明業(yè)務(wù)方法
- ConcreteProduct:具體產(chǎn)品,實(shí)現(xiàn)抽象產(chǎn)品中聲明的方法
優(yōu)點(diǎn)
創(chuàng)建細(xì)節(jié)對(duì)客戶(hù)端完全隱藏,這使得更換一個(gè)具體工廠變得容易,不同的環(huán)境決定軟件的不同行為,因此抽象工廠得到了廣泛應(yīng)用
-
增加新的產(chǎn)品族很方便,只需增加具體產(chǎn)品和具體工廠,符合”開(kāi)閉原則“
開(kāi)閉原則:對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉,增加新功能新模塊不會(huì)修改原來(lái)代碼,不影響原來(lái)的測(cè)試和運(yùn)行。
缺點(diǎn)
- 增加新的產(chǎn)品等級(jí),需要擴(kuò)展現(xiàn)有的抽象工廠,這會(huì)涉及到全部具體工廠的修改,違背了“開(kāi)閉原則”
- 開(kāi)閉原則的傾斜性
- 增加產(chǎn)品族:符合”開(kāi)閉原則“
- 增加產(chǎn)品等級(jí):不符合”開(kāi)閉原則“
何時(shí)使用
- 不關(guān)心產(chǎn)品創(chuàng)建細(xì)節(jié),將產(chǎn)品創(chuàng)建和使用解耦
- 系統(tǒng)中有多個(gè)產(chǎn)品族,但每次只使用一個(gè),示例中如果同時(shí)購(gòu)進(jìn)小米產(chǎn)品和華為產(chǎn)品將使設(shè)計(jì)模式失去優(yōu)勢(shì)
- 根據(jù)環(huán)境不同軟件有不同的行為
- 系統(tǒng)穩(wěn)定后,不會(huì)添加新的產(chǎn)品等級(jí)或者刪除已有的產(chǎn)品等級(jí)
工廠模式
當(dāng)抽象工廠只含有一個(gè)產(chǎn)品等級(jí),也就是抽象工廠只聲明一個(gè)方法時(shí),抽象工廠模式退化為工廠模式, 這時(shí)候每個(gè)具體工廠只能生產(chǎn)一種產(chǎn)品。
簡(jiǎn)單工廠模式
沒(méi)有抽象工廠,具體工廠只有一個(gè)創(chuàng)建產(chǎn)品實(shí)例的靜態(tài)方法,這個(gè)方法根據(jù)不同的參數(shù)創(chuàng)建不同的產(chǎn)品。簡(jiǎn)單工廠模式不屬于23種設(shè)計(jì)模式,因?yàn)樗?jiǎn)單了。
總結(jié)
雖然有這么多工廠,但是使用最廣泛,最好用的還是抽象工廠模式。