工廠設(shè)計(jì)模式
工廠設(shè)計(jì)模式是一種創(chuàng)建型設(shè)計(jì)模式,它提供了一種在不指定具體類(lèi)的情況下創(chuàng)建對(duì)象的接口。在工廠設(shè)計(jì)模式中,我們定義一個(gè)創(chuàng)建對(duì)象的接口,讓子類(lèi)決定實(shí)例化哪一個(gè)類(lèi)。工廠方法使一個(gè)類(lèi)的實(shí)例化延遲到其子類(lèi)。
工廠設(shè)計(jì)模式的目的是:
- 封裝對(duì)象創(chuàng)建的過(guò)程,使得用戶不需要了解對(duì)象的實(shí)現(xiàn)細(xì)節(jié)。
- 擴(kuò)展性良好,如果需要添加新的對(duì)象,只需添加一個(gè)新的子類(lèi)即可。
- 遵循“開(kāi)閉原則”,即對(duì)擴(kuò)展開(kāi)放,對(duì)修改封閉。
在java中,萬(wàn)物皆對(duì)象,這些對(duì)象都需要?jiǎng)?chuàng)建,如果創(chuàng)建的時(shí)候直接new該對(duì)象,就會(huì)對(duì)該對(duì)象耦合嚴(yán)重,假如我們要更換對(duì)象,所有new對(duì)象的地方都需要修改一遍,這顯然違背了軟件設(shè)計(jì)的開(kāi)閉原則。如果我們使用工廠來(lái)生產(chǎn)對(duì)象,我們就只和工廠打交道就可以了,徹底和對(duì)象解耦,如果要更換對(duì)象,直接在工廠里更換該對(duì)象即可,達(dá)到了與對(duì)象解耦的目的;所以說(shuō),工廠模式最大的優(yōu)點(diǎn)就是:解耦。
工廠模式的主要功能就是幫助我們實(shí)例化對(duì)象的,之所以名字中包含工廠模式四個(gè)字,是因?yàn)閷?duì)象的實(shí)例化過(guò)程是通過(guò)工廠實(shí)現(xiàn)的,是用工廠代替new操作的。
這樣做可以封裝對(duì)象的實(shí)例化細(xì)節(jié),尤其是對(duì)于實(shí)例化比較復(fù)雜或者對(duì)象的生命周期應(yīng)該集中管理的情況。會(huì)給你系統(tǒng)帶來(lái)更大的可擴(kuò)展性和盡量少的修改量。
工廠模式有三種,分別是簡(jiǎn)單工廠模式,工廠方法模式,抽象工廠模式。三種模式從前到后越來(lái)越抽象,也更具有一般性。
簡(jiǎn)單工廠模式:
簡(jiǎn)單工廠模式并不屬于23種設(shè)計(jì)模式,其更像是一種編程習(xí)慣。
簡(jiǎn)單工廠模式結(jié)構(gòu):
簡(jiǎn)單工廠包含如下角色:
- 抽象產(chǎn)品 :定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能。
- 具體產(chǎn)品 :實(shí)現(xiàn)或者繼承抽象產(chǎn)品的子類(lèi)
- 具體工廠 :提供了創(chuàng)建產(chǎn)品的方法,調(diào)用者通過(guò)該方法來(lái)獲取產(chǎn)品。
列舉實(shí)現(xiàn)
抽象產(chǎn)品類(lèi):小米SU7
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 小米SU7抽象類(lèi)
*/
public abstract class XiaoMiSU7 {
public void run(){
System.out.println("百公里加速2.8");
}
public void stop(){
System.out.println("黃色剎車(chē)盤(pán)");
}
// 獲取配置
public abstract String getDisposition();
}
具體產(chǎn)品:低配版小米SU7
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 低配小米SU7
*/
public class LowConfigurationSU7 extends XiaoMiSU7 {
@Override
public String getDisposition() {
return "低配小米SU7";
}
}
具體產(chǎn)品:高配版小米SU7
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 高配小米SU7
*/
public class HighConfigurationSU7 extends XiaoMiSU7{
@Override
public String getDisposition() {
return "高配小米SU7";
}
}
具體工廠類(lèi):
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 小米SU7靜態(tài)工廠
*/
public class SimpleSU7Factory {
/**
* 根據(jù)不同配置生產(chǎn)小米SU7 靜態(tài)方法,直接通過(guò)類(lèi)名打點(diǎn)調(diào)用即可
* @param type 不同配置
* @return 不同配置的小米SU7
*/
public XiaoMiSU7 createXiaoMiSU7(String type) {
XiaoMiSU7 xiaoMiSU7 = null;
if ("high".equals(type)) {
xiaoMiSU7 = new HighConfigurationSU7();
} else if ("low".equals(type)) {
xiaoMiSU7 = new LowConfigurationSU7();
}
return xiaoMiSU7;
}
}
通過(guò)以上的簡(jiǎn)單工廠模式,我們?cè)谛∶?S店類(lèi)中,只需要使用SU7工廠類(lèi)直接生產(chǎn)SU7即可,不需要再將4S店類(lèi)與高配版SU7以及低配版SU7類(lèi)之間進(jìn)行耦合,達(dá)到了解耦的目的。
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 小米4S店
*/
public class MI4S {
/**
* 訂購(gòu)小米SU7
* @param type 訂購(gòu)類(lèi)型(高配,低配)
* @return (高配,低配)小米SU7
*/
public XiaoMiSU7 orderXiaoMiSU7(String type) {
SimpleSU7Factory su7Factory = new SimpleSU7Factory();
XiaoMiSU7 xiaoMiSU7 = su7Factory.createXiaoMiSU7(type);
xiaoMiSU7.run();
xiaoMiSU7.stop();
return xiaoMiSU7;
}
}
優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
封裝了創(chuàng)建對(duì)象的過(guò)程,可以通過(guò)參數(shù)直接獲取對(duì)象。把對(duì)象的創(chuàng)建和業(yè)務(wù)邏輯層分開(kāi),這樣以后就避免了修改客戶代碼,如果要實(shí)現(xiàn)新產(chǎn)品直接修改工廠類(lèi),而不需要在原代碼中修改,這樣就降低了客戶代碼修改的可能性,更加容易擴(kuò)展。
缺點(diǎn):
增加新產(chǎn)品時(shí)還是需要修改工廠類(lèi)的代碼,違背了“開(kāi)閉原則”。
擴(kuò)展:靜態(tài)工廠模式
我們可以將工廠中的創(chuàng)建產(chǎn)品的方法設(shè)置為工廠類(lèi)的靜態(tài)方法,這樣我們?cè)?S店中只需要通過(guò)工廠類(lèi)名之間打點(diǎn)調(diào)用創(chuàng)建產(chǎn)品方法即可,無(wú)序去實(shí)例化工廠對(duì)象。
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 小米SU7靜態(tài)工廠
*/
public class SimpleSU7Factory {
/**
* 根據(jù)不同配置生產(chǎn)小米SU7 靜態(tài)方法,直接通過(guò)類(lèi)名打點(diǎn)調(diào)用即可
* @param type 不同配置
* @return 不同配置的小米SU7
*/
public static XiaoMiSU7 createXiaoMiSU7(String type) {
XiaoMiSU7 xiaoMiSU7 = null;
if ("high".equals(type)) {
xiaoMiSU7 = new HighConfigurationSU7();
} else if ("low".equals(type)) {
xiaoMiSU7 = new LowConfigurationSU7();
}
return xiaoMiSU7;
}
}
通過(guò)以上優(yōu)缺點(diǎn)分析,我們發(fā)現(xiàn)簡(jiǎn)單工廠模式模式雖然把對(duì)象的創(chuàng)建和業(yè)務(wù)邏輯層分開(kāi),但是如果我們想要進(jìn)行拓展,任然需要手動(dòng)修改工廠方法中創(chuàng)建對(duì)象的邏輯,這顯然也是不符合‘開(kāi)閉原則’的,因此,我們可以使用簡(jiǎn)單工廠模式+配置文件的方式,解決這一問(wèn)題。
可以通過(guò)工廠模式+配置文件的方式解除工廠對(duì)象和產(chǎn)品對(duì)象的耦合。在工廠類(lèi)中加載配置文件中的全類(lèi)名,并創(chuàng)建對(duì)象進(jìn)行存儲(chǔ),客戶端如果需要對(duì)象,直接進(jìn)行獲取即可。
第一步:定義配置文件
為了演示方便,我們使用properties文件作為配置文件,名稱為bean.properties
american=com.tyut.pattern._01_creative_model.e02factor.config_factory.AmericanCoffee
latte=com.tyut.pattern._01_creative_model.e02factor.config_factory.LatteCoffee
ku=com.tyut.pattern._01_creative_model.e02factor.config_factory.KuCoffee
第二步:改進(jìn)工廠類(lèi)
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 簡(jiǎn)單咖啡工廠類(lèi) - 通過(guò)加載配置文件的方式,實(shí)現(xiàn)開(kāi)閉原則,
* 解除簡(jiǎn)單工廠類(lèi)和具體產(chǎn)品類(lèi)之間的耦合
*/
public class CoffeeFactory {
//定義一個(gè)map容器存儲(chǔ)對(duì)象
private static final Map<String, Coffee> map = new HashMap<>();
/*
* 在靜態(tài)代碼塊中加載配置文件并創(chuàng)建對(duì)象
*/
static {
InputStream resource = CoffeeFactory.class.getClassLoader()
.getResourceAsStream("bean.properties");
Properties properties = new Properties();
try {
properties.load(resource);
Set<Object> keySet = properties.keySet();
for (Object key : keySet) {
String className = properties.getProperty((String) key);
// 通過(guò)類(lèi)的全限定路徑創(chuàng)建類(lèi)的反射(字節(jié)碼)對(duì)象
Class<?> clazz = Class.forName(className);
// 通過(guò)反射對(duì)象調(diào)用類(lèi)的無(wú)參構(gòu)造實(shí)例化類(lèi)
Coffee coffee = (Coffee) clazz.newInstance();
map.put((String) key, coffee);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//創(chuàng)建對(duì)象
public static Coffee createCoffee(String type) {
return map.get(type);
}
}
靜態(tài)成員變量用來(lái)存儲(chǔ)創(chuàng)建的對(duì)象(鍵存儲(chǔ)的是名稱,值存儲(chǔ)的是對(duì)應(yīng)的對(duì)象),而讀取配置文件以及創(chuàng)建對(duì)象寫(xiě)在靜態(tài)代碼塊中,目的就是只需要執(zhí)行一次。
通過(guò)以上代碼改進(jìn)工廠類(lèi),我們就可以通過(guò)讀取配置文件中的配置,將需要的對(duì)象通過(guò)反射技術(shù)創(chuàng)建并加入容器中,在creat
方法中,只需要通過(guò)參數(shù)獲取容器中的對(duì)象并返回即可,這樣就可以實(shí)現(xiàn)工廠類(lèi)與具體產(chǎn)品類(lèi)之間解耦,如果需要添加具體產(chǎn)品,只需要?jiǎng)?chuàng)建新增產(chǎn)品類(lèi)并且在配置文件中加入新增產(chǎn)品的全限定路徑即可,工廠類(lèi)會(huì)在類(lèi)加載階段就將產(chǎn)品類(lèi)創(chuàng)建并加入容器,無(wú)序修改工廠類(lèi),實(shí)現(xiàn)了“開(kāi)閉原則”!
工廠方法模式
概念
定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類(lèi)決定實(shí)例化哪個(gè)產(chǎn)品類(lèi)對(duì)象。工廠方法使一個(gè)產(chǎn)品類(lèi)的實(shí)例化延遲到其工廠的子類(lèi)。
工廠方法模式結(jié)構(gòu)
工廠方法模式的主要角色:
- 抽象工廠(Abstract Factory):提供了創(chuàng)建產(chǎn)品的接口,調(diào)用者通過(guò)它訪問(wèn)具體工廠的工廠方法來(lái)創(chuàng)建產(chǎn)品。
- 具體工廠(ConcreteFactory):主要是實(shí)現(xiàn)抽象工廠中的抽象方法,完成具體產(chǎn)品的創(chuàng)建。
- 抽象產(chǎn)品(Product):定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能。
- 具體產(chǎn)品(ConcreteProduct):實(shí)現(xiàn)了抽象產(chǎn)品角色所定義的接口,由具體工廠來(lái)創(chuàng)建,它同具體工廠之間一一對(duì)應(yīng)。
列舉實(shí)現(xiàn)
抽象產(chǎn)品:
抽象產(chǎn)品類(lèi):小米SU7
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 小米SU7抽象類(lèi)
*/
public abstract class XiaoMiSU7 {
public void run(){
System.out.println("百公里加速2.8");
}
public void stop(){
System.out.println("黃色剎車(chē)盤(pán)");
}
// 獲取配置
public abstract String getDisposition();
}
具體產(chǎn)品:低配版小米SU7
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 低配小米SU7
*/
public class LowConfigurationSU7 extends XiaoMiSU7 {
@Override
public String getDisposition() {
return "低配小米SU7";
}
}
具體產(chǎn)品:高配版小米SU7
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 高配小米SU7
*/
public class HighConfigurationSU7 extends XiaoMiSU7{
@Override
public String getDisposition() {
return "高配小米SU7";
}
}
抽象工廠類(lèi):
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 抽象工廠
*/
public interface XiaoMiSU7Factory {
XiaoMiSU7 createXiaoMiSU7();
}
為每一個(gè)具體產(chǎn)品都創(chuàng)建一個(gè)與之對(duì)應(yīng)的具體工廠用來(lái)創(chuàng)建具體產(chǎn)品實(shí)例。
具體工廠類(lèi):低配版SU7工廠
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 低配小米SU7工廠
*/
public class LowXiaoMiSU7Factory implements XiaoMiSU7Factory {
@Override
public XiaoMiSU7 createXiaoMiSU7() {
return new LowConfigurationSU7();
}
}
具體工廠類(lèi):高配版SU7工廠
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 高配小米SU7工廠
*/
public class HighXiaoMiSU7Factory implements XiaoMiSU7Factory {
@Override
public XiaoMiSU7 createXiaoMiSU7() {
return new HighConfigurationSU7();
}
}
小米4S店類(lèi):
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 小米4S店
*/
public class MI4S {
private XiaoMiSU7Factory factory;
public void setFactory(XiaoMiSU7Factory factory) {
this.factory = factory;
}
/**
* 訂購(gòu)小米SU7
*
* @return 小米SU7
*/
public XiaoMiSU7 orderXiaoMiSU7() {
XiaoMiSU7 xiaoMiSU7 = factory.createXiaoMiSU7();
xiaoMiSU7.run();
xiaoMiSU7.stop();
return xiaoMiSU7;
}
}
工廠方法模式是簡(jiǎn)單工廠模式的進(jìn)一步抽象。由于使用了多態(tài)性,工廠方法模式保持了簡(jiǎn)單工廠模式的優(yōu)點(diǎn),而且克服了它的缺點(diǎn)。
在小米4S店類(lèi)中,我們只需聲明一個(gè)抽象工廠類(lèi)型的成員變量,并且調(diào)用其創(chuàng)建SU7方法即可,具體創(chuàng)建什么類(lèi)型的SU7并不需要我們關(guān)心,只需要在客戶端傳入不同類(lèi)型的工廠對(duì)象即可,通過(guò)這種工廠方法模式,我們將工廠類(lèi)和具體產(chǎn)品類(lèi)完全解耦(一個(gè)工廠只負(fù)責(zé)生產(chǎn)一種具體產(chǎn)品),并且如果我們還要拓展一個(gè)具體產(chǎn)品,如中配版SU7,我們只需創(chuàng)建新的具體產(chǎn)品類(lèi)以及具體工廠類(lèi)并讓其實(shí)現(xiàn)其抽象即可,無(wú)序修改工廠類(lèi)代碼,符合“開(kāi)閉原則”。
優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 用戶只需要知道具體工廠的名稱就可得到所要的產(chǎn)品,無(wú)須知道產(chǎn)品的具體創(chuàng)建過(guò)程;
- 在系統(tǒng)增加新的產(chǎn)品時(shí)只需要添加具體產(chǎn)品類(lèi)和對(duì)應(yīng)的具體工廠類(lèi),無(wú)須對(duì)原工廠進(jìn)行任何修改,滿足開(kāi)閉原則;
缺點(diǎn):
- 每增加一個(gè)產(chǎn)品就要增加一個(gè)具體產(chǎn)品類(lèi)和一個(gè)對(duì)應(yīng)的具體工廠類(lèi),這增加了系統(tǒng)的復(fù)雜度。
抽象工廠模式
前面介紹的工廠方法模式中考慮的是一類(lèi)產(chǎn)品的生產(chǎn),如畜牧場(chǎng)只養(yǎng)動(dòng)物、電視機(jī)廠只生產(chǎn)電視機(jī)。
這些工廠只生產(chǎn)同種類(lèi)產(chǎn)品,同種類(lèi)產(chǎn)品稱為同等級(jí)產(chǎn)品,也就是說(shuō):工廠方法模式只考慮生產(chǎn)同等級(jí)的產(chǎn)品,但是在現(xiàn)實(shí)生活中許多工廠是綜合型的工廠,能生產(chǎn)多等級(jí)(種類(lèi)) 的產(chǎn)品,如電器廠既生產(chǎn)電視機(jī)又生產(chǎn)洗衣機(jī)或空調(diào),大學(xué)既有軟件專(zhuān)業(yè)又有生物專(zhuān)業(yè)等。
抽象工廠模式將考慮多等級(jí)產(chǎn)品的生產(chǎn),將同一個(gè)具體工廠所生產(chǎn)的位于不同等級(jí)的一組產(chǎn)品稱為一個(gè)產(chǎn)品族。
產(chǎn)品族:位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中,功能相關(guān)的產(chǎn)品組成的家族。
概念
是一種為訪問(wèn)類(lèi)提供一個(gè)創(chuàng)建一組相關(guān)或相互依賴對(duì)象的接口,且訪問(wèn)類(lèi)無(wú)須指定所要產(chǎn)品的具體類(lèi)就能得到同族的不同等級(jí)的產(chǎn)品的模式結(jié)構(gòu)。
抽象工廠模式是工廠方法模式的升級(jí)版本,工廠方法模式只生產(chǎn)一個(gè)等級(jí)的產(chǎn)品,而抽象工廠模式可生產(chǎn)多個(gè)等級(jí)的產(chǎn)品。
抽象工廠模式結(jié)構(gòu)
抽象工廠模式的主要角色如下:
- 抽象工廠(Abstract Factory):提供了創(chuàng)建產(chǎn)品的接口,它包含多個(gè)創(chuàng)建產(chǎn)品的方法,可以創(chuàng)建多個(gè)不同等級(jí)的產(chǎn)品。
- 具體工廠(Concrete Factory):主要是實(shí)現(xiàn)抽象工廠中的多個(gè)抽象方法,完成具體產(chǎn)品的創(chuàng)建。
- 抽象產(chǎn)品(Product):定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能,抽象工廠模式有多個(gè)抽象產(chǎn)品。
- 具體產(chǎn)品(ConcreteProduct):實(shí)現(xiàn)了抽象產(chǎn)品角色所定義的接口,由具體工廠來(lái)創(chuàng)建,它同具體工廠之間是多對(duì)一的關(guān)系。
列舉實(shí)現(xiàn)
抽象產(chǎn)品類(lèi):咖啡類(lèi)
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 抽象產(chǎn)品 - 咖啡
*/
public abstract class Coffee {
public abstract String getName();
public void addSugar(){
System.out.println("加糖");
}
public void addMilk(){
System.out.println("加奶");
}
}
抽象產(chǎn)品類(lèi):甜品類(lèi)
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 抽象產(chǎn)品 - 甜品
*/
public abstract class Dessert {
public abstract String getName();
}
咖啡類(lèi)和甜品類(lèi)同屬于甜點(diǎn)產(chǎn)品族中不同等級(jí)的產(chǎn)品。
具體產(chǎn)品類(lèi):
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 具體產(chǎn)品 - 拿鐵咖啡
*/
public class LatteCoffee extends Coffee{
@Override
public String getName() {
return "拿鐵咖啡";
}
}
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 具體產(chǎn)品 - 美式咖啡
*/
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
}
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 具體產(chǎn)品 - 抹茶慕斯
*/
public class MatchaMousse extends Dessert{
@Override
public String getName() {
return "抹茶慕斯";
}
}
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 具體產(chǎn)品 - 提拉米蘇
*/
public class Tiramisu extends Dessert {
@Override
public String getName() {
return "提拉米蘇";
}
}
具體產(chǎn)品分別繼承自各自產(chǎn)品等級(jí)的頂層抽象,并實(shí)現(xiàn)其抽象方法。
抽象工廠類(lèi):甜點(diǎn)產(chǎn)品族
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 抽象工廠 - 甜點(diǎn)接口
*/
public interface DessertFactory {
Dessert createDessert();
Coffee createCoffee();
}
抽象工廠模式中,一個(gè)抽象工廠類(lèi)中提供了多個(gè)同一產(chǎn)品族產(chǎn)品的生產(chǎn)方法。
例如:一個(gè)甜點(diǎn)類(lèi)抽象工廠中,提供了生產(chǎn)咖啡方法和生產(chǎn)甜品方法。
具體工廠類(lèi):意大利風(fēng)味甜點(diǎn)
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 具體工廠 - 意大利風(fēng)味甜點(diǎn)
*/
public class ItalyDessertFactory implements DessertFactory {
@Override
public Dessert orderDessert() {
return new Tiramisu();
}
@Override
public Coffee orderCoffee() {
return new LatteCoffee();
}
}
具體工廠類(lèi):美式風(fēng)味甜點(diǎn)
/**
* @author OldGj 2024/02/20
* @version v1.0
* @apiNote 具體工廠 - 美式風(fēng)味甜點(diǎn)
*/
public class AmericanDessertFactory implements DessertFactory {
@Override
public Dessert orderDessert() {
return new MatchaMousse();
}
@Override
public Coffee orderCoffee() {
return new AmericanCoffee();
}
}
如果要加同一個(gè)產(chǎn)品族的話,只需要再加一個(gè)對(duì)應(yīng)的工廠類(lèi)即可,不需要修改其他的類(lèi)。
優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
當(dāng)一個(gè)產(chǎn)品族中的多個(gè)對(duì)象被設(shè)計(jì)成一起工作時(shí),它能保證客戶端始終只使用同一個(gè)產(chǎn)品族中的對(duì)象。
缺點(diǎn):
當(dāng)產(chǎn)品族中需要增加一個(gè)新的產(chǎn)品時(shí),所有的工廠類(lèi)都需要進(jìn)行修改。
"開(kāi)閉原則"的傾斜性
"開(kāi)閉原則”要求系統(tǒng)對(duì)拓展開(kāi)放,對(duì)修改關(guān)閉,通過(guò)擴(kuò)展達(dá)到增強(qiáng)其功能的目的。對(duì)于涉及到多個(gè)產(chǎn)品族與多個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)的系統(tǒng),其功能增強(qiáng)包括兩方面:
- 增加產(chǎn)品族:對(duì)于增加新的產(chǎn)品族,工廠方法模式很好的支持了“開(kāi)閉原則”,對(duì)于新增加的產(chǎn)品族,只需要對(duì)應(yīng)增加一個(gè)新的具體工廠即可,對(duì)已有代碼無(wú)序做任何修改。
- 增加新的產(chǎn)品等級(jí)結(jié)構(gòu):對(duì)于增加新的產(chǎn)品等級(jí)結(jié)構(gòu),需要修改所有的工廠角色,包括抽象工廠類(lèi),在所有的工廠類(lèi)中都需要增加生產(chǎn)新產(chǎn)品的方法,不能很好的支持“開(kāi)閉原則”。
抽象工廠模式的這種性質(zhì)稱為“開(kāi)閉原則”的傾斜性,抽象工廠模式以一種傾斜的方式支持增加新的產(chǎn)品,它為新產(chǎn)品族的增加提供方便,但不能為新的產(chǎn)品等級(jí)結(jié)構(gòu)的增加提供方便。
抽象工廠模式總結(jié)
抽象工廠模式提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無(wú)須指定它們具體的類(lèi)。抽象工廠模式又稱為Kit模式,屬于對(duì)象創(chuàng)建型模式。
抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形態(tài)。
抽象工廠模式的主要優(yōu)點(diǎn)是隔離了具體類(lèi)的生成,使得客戶并不需要知道什么被創(chuàng)建,而且每次可以通過(guò)具體工廠類(lèi)創(chuàng)建一個(gè)產(chǎn)品族中的多個(gè)對(duì)象,增加或者替換產(chǎn)品族比較方便,增加新的具體工廠和產(chǎn)品族很方便;主要缺點(diǎn)在于增加新的產(chǎn)品等級(jí)結(jié)構(gòu)很復(fù)雜,需要修改抽象工廠和所有的具體工廠類(lèi),對(duì)“開(kāi)閉原則”的支持呈現(xiàn)傾性。
使用場(chǎng)景
-
當(dāng)需要?jiǎng)?chuàng)建的對(duì)象是一系列相互關(guān)聯(lián)或相互依賴的產(chǎn)品族時(shí),如電器工廠中的電視機(jī)、洗衣機(jī)、空調(diào)等。
-
系統(tǒng)中有多個(gè)產(chǎn)品族,但每次只使用其中的某一族產(chǎn)品。如有人只喜歡穿某一個(gè)品牌的衣服和鞋。
-
系統(tǒng)中提供了產(chǎn)品的類(lèi)庫(kù),且所有產(chǎn)品的接口相同,客戶端不依賴產(chǎn)品實(shí)例的創(chuàng)建細(xì)節(jié)和內(nèi)部結(jié)構(gòu)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-835487.html
JDK中的工廠模式:
- Collection.iterator方法
Collection接口是抽象工廠類(lèi)
ArrayList是具體的工廠類(lèi)
Iterator接口是抽象商品類(lèi)
ArrayList類(lèi)中的Itr內(nèi)部類(lèi)是具體的商品類(lèi)。
在具體的工廠類(lèi)中iterator()方法創(chuàng)建具體的商品類(lèi)的對(duì)象。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-835487.html
- DateForamt類(lèi)中的getInstance()方法使用的是工廠模式;
- ,Calendar類(lèi)中的getInstance()方法使用的是工廠模式;
到了這里,關(guān)于【深入理解設(shè)計(jì)模式】 工廠設(shè)計(jì)模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!