02.工廠模式設計思想
目錄介紹
- 01.工廠模式設計
- 1.1 工廠模式類型
- 1.2 工廠模式思考
- 1.3 思考一個題目
- 02.簡單工廠介紹
- 2.1 簡單工廠背景
- 2.2 簡單工廠定義
- 2.3 簡單工廠結(jié)構(gòu)
- 2.4 簡單工廠案例
- 2.5 簡單工廠分析
- 2.6 簡單工廠場景
- 2.7 簡單工廠不足
- 03.工廠方法介紹
- 3.1 工廠方法背景
- 3.2 工廠方法定義
- 3.3 工廠方法結(jié)構(gòu)
- 3.4 工廠方法案例
- 3.5 工廠方法分析
- 3.6 工廠方法場景
- 3.7 工廠方法不足
- 04.抽象工廠介紹
- 4.1 抽象工廠背景
- 4.2 抽象工廠定義
- 4.3 抽象工廠結(jié)構(gòu)
- 4.4 抽象工廠案例
- 4.5 抽象工廠分析
- 4.6 抽象工廠場景
- 4.7 抽象工廠不足
- 05.工廠模式總結(jié)
- 5.1 工廠設計總結(jié)
- 5.2 如何選擇
- 5.3 更多內(nèi)容推薦
01.工廠模式設計
1.1 工廠模式類型
一般情況下,工廠模式分為三種更加細分的類型:簡單工廠搜骡、工廠方法和抽象工廠它呀。
不過,在 GoF 的《設計模式》一書中哥遮,它將簡單工廠模式看作是工廠方法模式的一種特例笨使,所以工廠模式只被分成了工廠方法和抽象工廠兩類镀裤。
實際上竞阐, 在這三種細分的工廠模式中,簡單工廠暑劝、工廠方法原理比較簡單骆莹,在實際的項目中也比較常用。而抽象工廠的原理稍微復雜點铃岔,在實際的項目中相對也不常用汪疮。
1.2 工廠模式思考
講解的重點也不是原理和實現(xiàn),因為這些都很簡單毁习,重點還是帶你搞清楚應用場景智嚷。什么時候該用工廠模式?相對于直接 new 來創(chuàng)建對象纺且,用工廠模式來創(chuàng)建究竟有什么好處呢盏道?
1.3 思考一個題目
你現(xiàn)在是一個做咖啡的老板。你要在店里買各種咖啡载碌,而這些咖啡中有的加冰猜嘱,有的加奶衅枫,有的加糖。比如美式咖啡朗伶,拿鐵咖啡弦撩,摩卡咖啡,巴西咖啡等等论皆!你需要設計一個咖啡店點餐系統(tǒng)益楼!
簡單工廠實現(xiàn):設計一個咖啡類(Coffee),并定義其兩個子類(美式咖啡AmericanCoffee和拿鐵咖啡LatteCoffee)点晴;再設計一個咖啡店類(CoffeeStore)感凤,咖啡店具有點咖啡的功能。
- 創(chuàng)造抽象產(chǎn)品角色粒督,比如總結(jié)出很多咖啡都可能會嚣艇,加糖皆撩,加冰肥败,加奶烤芦,因此把它抽成抽象方法。
- 具體產(chǎn)品角色仇矾,這塊有:美式咖啡類庸蔼,拿鐵咖啡類解总,摩卡咖啡等贮匕,這些都是具體的咖啡產(chǎn)品。
- 工廠角色花枫。負責創(chuàng)建不同咖啡刻盐,為了簡便高效地分配咖啡,設了根據(jù)類型(比如
american
劳翰,latte
)來提供不同的咖啡敦锌。
新增需求1: 后期我想要再增加一個或者多個新的咖啡,簡單工廠這個案例則需要修改工廠角色佳簸,這個違背了開閉原則乙墙。那有什么好的方式解決呢?可以用工廠方法模式生均。
工廠方法實現(xiàn):
- Product:抽象產(chǎn)品听想。這個和簡單工廠模式代碼一樣,忽略马胧!
- ConcreteProduct:具體產(chǎn)品汉买。這個和簡單工廠模式代碼一樣,忽略佩脊!
- Factory:抽象工廠蛙粘。這塊定義咖啡工廠接口垫卤,通過該接口子類可以自己實現(xiàn)咖啡創(chuàng)建。
- ConcreteFactory:具體工廠出牧。這里主要是創(chuàng)建美式咖啡工廠類穴肘,創(chuàng)建拿鐵咖啡工廠類。
新增需求2: 后期咖啡點業(yè)務增多舔痕,現(xiàn)在不僅生產(chǎn)咖啡梢褐,還要生產(chǎn)甜點,請用抽象工廠去實現(xiàn)咖啡店咖啡和甜點的生產(chǎn)赵讯。這個可以用到抽象工廠模式盈咳。
抽象工廠實現(xiàn):
- AbstractFactory:抽象工廠。這個時候則需要抽象出生產(chǎn)甜品边翼,生產(chǎn)咖啡的接口鱼响。
- ConcreteFactory:具體工廠。分別實現(xiàn)生產(chǎn)甜品的具體工廠组底,生產(chǎn)咖啡的具體工廠丈积。
- AbstractProduct:抽象產(chǎn)品。這里把甜點抽象成一個產(chǎn)品债鸡,把咖啡抽象成一個產(chǎn)品江滨。
- Product:具體產(chǎn)品。創(chuàng)建具體的美式咖啡厌均,拿鐵咖啡產(chǎn)品唬滑。創(chuàng)建具體的提拉米蘇甜點,抹茶慕斯甜點棺弊。
02.簡單工廠介紹
2.1 簡單工廠背景
考慮一個簡單的軟件應用場景晶密,一個軟件系統(tǒng)可以提供多個外觀不同的按鈕(如圓形按鈕、矩形按鈕模她、菱形按鈕等)稻艰,這些按鈕都源自同一個基類,不過在繼承基類后不同的子類修改了部分屬性從而使得它們可以呈現(xiàn)不同的外觀侈净。
如果我們希望在使用這些按鈕時尊勿,不需要知道這些具體按鈕類的名字,只需要知道表示該按鈕類的一個參數(shù)畜侦,并提供一個調(diào)用方便的方法元扔,把該參數(shù)傳入方法即可返回一個相應的按鈕對象,此時夏伊,就可以使用簡單工廠模式摇展。
2.2 簡單工廠定義
簡單工廠模式(Simple Factory Pattern):又稱為靜態(tài)工廠方法(Static Factory Method)模式,它屬于類創(chuàng)建型模式。在簡單工廠模式中咏连,可以根據(jù)參數(shù)的不同返回不同類的實例盯孙。簡單工廠模式專門定義一個類來負責創(chuàng)建其他類的實例,被創(chuàng)建的實例通常都具有共同的父類祟滴。
2.3 簡單工廠結(jié)構(gòu)
簡單工廠模式包含如下角色:
- Factory:工廠角色 振惰。工廠角色負責實現(xiàn)創(chuàng)建所有實例的內(nèi)部邏輯
- Product:抽象產(chǎn)品角色 。抽象產(chǎn)品角色是所創(chuàng)建的所有對象的父類垄懂,負責描述所有實例所共有的公共接口
- ConcreteProduct:具體產(chǎn)品角色 骑晶。具體產(chǎn)品角色是創(chuàng)建目標,所有創(chuàng)建的對象都充當這個角色的某個具體類的實例草慧。
2.4 簡單工廠案例
創(chuàng)造抽象產(chǎn)品角色桶蛔,比如總結(jié)出很多咖啡都可能會,加糖漫谷,加冰仔雷,加奶,因此把它抽成抽象方法舔示。
// 咖啡類(父類)--抽象類
public abstract class Coffee {
//每個咖啡都有名字碟婆,所以抽取到父類,定義為抽象方法
public abstract String getName();
public void addMilk() {
System.out.println("加奶...");
}
public void addSugar() {
System.out.println("加糖...");
}
}
具體產(chǎn)品角色惕稻,這塊有:美式咖啡類竖共,拿鐵咖啡類,摩卡咖啡等俺祠,這些都是具體的咖啡產(chǎn)品公给。
// 美式咖啡類 繼承 咖啡類
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
public void show() {
System.out.println("我是美式咖啡....");
}
}
// 拿鐵咖啡類 繼承 咖啡類
public class LatteCoffee extends Coffee {
@Override
public String getName() {
return "拿鐵咖啡";
}
}
工廠角色。負責創(chuàng)建不同咖啡锻煌,為了簡便高效地分配咖啡妓布,設了根據(jù)類型(比如american
姻蚓,latte
)來提供不同的咖啡宋梧。
// 咖啡工廠
public class SimpleFactory {
//提供方法,創(chuàng)建具體咖啡
public Coffee createCoffee(String type) {
Coffee coffee = null;
if ("american".equals(type)) {
coffee = new AmericanCoffee(); //多態(tài)
} else if ("latte".equals(type)) {
coffee = new LatteCoffee(); //多態(tài)
} else {
throw new RuntimeException("沒有這種咖啡!");
}
return coffee;
}
}
盡管簡單工廠模式的代碼實現(xiàn)中狰挡,有多處 if 分支判斷邏輯捂龄,違背開閉原則,但權衡擴展性和可讀性加叁,這樣的代碼實現(xiàn)在大多數(shù)情況下(比如倦沧,不需要頻繁地添加不同類型咖啡)是沒有問題的。
最后就是咖啡點通過不同類型創(chuàng)建不同的咖啡
private void test() {
// 創(chuàng)建咖啡店對象它匕,進行點咖啡
CoffeeStore store = new CoffeeStore();
//隱含了多態(tài)展融,在工廠里
Coffee coffee = store.orderCoffee("american");
String name = coffee.getName();
System.out.println(name);
//加糖...
//加奶...
//美式咖啡
}
// 咖啡店類
public class CoffeeStore {
public Coffee orderCoffee(String type) {
//此處解除了咖啡店類和具體的咖啡類的依賴,降低了耦合
// 創(chuàng)建工廠對象目的是創(chuàng)建具體的咖啡
SimpleFactory sf = new SimpleFactory();
// 創(chuàng)建咖啡豫柬,返回具體的咖啡對象
Coffee coffee = sf.createCoffee(type);
coffee.addSugar();
coffee.addMilk();
// 將具體的咖啡對象返回
return coffee;
}
}
思考一下這種場景告希,假如我們要更換對象(即扑浸,添加一個新的咖啡品種),我們勢必要需求修改SimpleCoffeeFactory的代碼燕偶,違反了開閉原則喝噪。
2.5 簡單工廠分析
將對象的創(chuàng)建和對象本身業(yè)務處理分離可以降低系統(tǒng)的耦合度,使得兩者修改起來都相對容易指么。
簡單工廠模式的要點在于:當你需要什么酝惧,只需要傳入一個正確的參數(shù),就可以獲取你所需要的對象伯诬,而無須知道其創(chuàng)建細節(jié)晚唇。
簡單工廠模式最大的問題在于工廠類的職責相對過重,增加新的產(chǎn)品需要修改工廠類的判斷邏輯盗似,這一點與開閉原則是相違背的缺亮。
2.6 簡單工廠場景
在以下情況下可以使用簡單工廠模式:
- 工廠類負責創(chuàng)建的對象比較少:由于創(chuàng)建的對象較少,不會造成工廠方法中的業(yè)務邏輯太過復雜桥言。
- 客戶端只知道傳入工廠類的參數(shù)萌踱,對于如何創(chuàng)建對象不關心:客戶端既不需要關心創(chuàng)建細節(jié),甚至連類名都不需要記住号阿,只需要知道類型所對應的參數(shù)并鸵。
模式應用場景
- JDK類庫中廣泛使用了簡單工廠模式,如工具類java.text.DateFormat扔涧,它用于格式化一個本地日期或者時間园担。
- Java加密技術,獲取不同加密算法的密鑰生成器: KeyGenerator keyGen=KeyGenerator.getInstance("DESede");
2.7 簡單工廠不足
缺點1: 使用簡單工廠模式將會增加系統(tǒng)中類的個數(shù)枯夜,在一定程序上增加了系統(tǒng)的復雜度和理解難度弯汰。舉個例子……
缺點2: 系統(tǒng)擴展困難,一旦添加新產(chǎn)品就不得不修改工廠邏輯湖雹,在產(chǎn)品類型較多時咏闪,有可能造成工廠邏輯過于復雜,不利于系統(tǒng)的擴展和維護摔吏。舉個例子……
缺點3: 由于工廠類集中了所有產(chǎn)品創(chuàng)建邏輯鸽嫂,一旦不能正常工作,整個系統(tǒng)都要受到影響征讲。違反了高內(nèi)聚的責任分配原則据某。
缺點4: 簡單工廠模式中的if else判斷非常多,完全是Hard Code诗箍,如果有一個新產(chǎn)品要加進來癣籽,就要同時添加一個新產(chǎn)品類,并且必須修改工廠類,再加入一個 else if 分支才可以筷狼, 這樣就違背了 “開放-關閉原則”中的對修改關閉的準則了橱夭。當系統(tǒng)中的具體產(chǎn)品類不斷增多時候,就要不斷的修改工廠類桑逝,對系統(tǒng)的維護和擴展不利棘劣。
03.工廠方法介紹
3.1 工廠方法背景
現(xiàn)在對該系統(tǒng)進行修改,不再設計一個按鈕工廠類來統(tǒng)一負責所有產(chǎn)品的創(chuàng)建楞遏,而是將具體按鈕的創(chuàng)建過程交給專門的工廠子類去完成茬暇,我們先定義一個抽象的按鈕工廠類,再定義具體的工廠類來生成圓形按鈕寡喝、矩形按鈕糙俗、菱形按鈕等,它們實現(xiàn)在抽象按鈕工廠類中定義的方法预鬓。
這種抽象化的結(jié)果使這種結(jié)構(gòu)可以在不修改具體工廠類的情況下引進新的產(chǎn)品巧骚,如果出現(xiàn)新的按鈕類型,只需要為這種新類型的按鈕創(chuàng)建一個具體的工廠類就可以獲得該新按鈕的實例格二,這一特點無疑使得工廠方法模式具有超越簡單工廠模式的優(yōu)越性劈彪,更加符合“開閉原則”。
3.2 工廠方法定義
工廠方法模式(Factory Method Pattern)又稱為工廠模式顶猜,也叫虛擬構(gòu)造器(Virtual Constructor)模式或者多態(tài)工廠(Polymorphic Factory)模式沧奴,它屬于類創(chuàng)建型模式。
在工廠方法模式中长窄,工廠父類負責定義創(chuàng)建產(chǎn)品對象的公共接口滔吠,而工廠子類則負責生成具體的產(chǎn)品對象,這樣做的目的是將產(chǎn)品類的實例化操作延遲到工廠子類中完成挠日,即通過工廠子類來確定究竟應該實例化哪一個具體產(chǎn)品類疮绷。
3.3 工廠方法結(jié)構(gòu)
工廠方法模式包含如下角色:
- Product:抽象產(chǎn)品。定義了產(chǎn)品的規(guī)范嚣潜,描述了產(chǎn)品的主要特性和功能冬骚。
- ConcreteProduct:具體產(chǎn)品。實現(xiàn)了抽象產(chǎn)品角色所定義的接口郑原,由具體工廠來創(chuàng)建唉韭,它同具體工廠之間一一對應。
- Factory:抽象工廠犯犁。提供了創(chuàng)建產(chǎn)品的接口,調(diào)用者通過抽象工廠訪問具體工廠(多態(tài))的工廠方法來創(chuàng)建產(chǎn)品對象女器。
- ConcreteFactory:具體工廠酸役。主要是實現(xiàn)抽象工廠中的抽象方法,完成具體產(chǎn)品的創(chuàng)建。
3.4 工廠方法案例
創(chuàng)建抽象產(chǎn)品涣澡。這里抽象出咖啡的公共特性贱呐,比如總結(jié)出很多咖啡都可能會,加糖入桂,加冰奄薇,加奶,因此把它抽成抽象方法抗愁。這個和簡單工廠模式代碼一樣馁蒂,忽略!
創(chuàng)建具體產(chǎn)品蜘腌。這塊有:美式咖啡類沫屡,拿鐵咖啡類,摩卡咖啡等撮珠,這些都是具體的咖啡產(chǎn)品沮脖。這個和簡單工廠模式代碼一樣,忽略芯急!
創(chuàng)建抽象接口工廠勺届。定義咖啡工廠接口,通過該接口子類可以自己實現(xiàn)咖啡創(chuàng)建娶耍。
// 定義咖啡工廠接口
public interface CoffeeFactory {
public abstract Coffee creatCoffee();
}
創(chuàng)建具體工廠涮因。這里主要是創(chuàng)建美式咖啡工廠類,創(chuàng)建拿鐵咖啡工廠類
// 創(chuàng)建拿鐵咖啡工廠類 實現(xiàn) 咖啡工廠類接口
public class LatteCoffeeFactory implements CoffeeFactory{
@Override
public Coffee creatCoffee() {
return new LatteCoffee();
}
}
// 創(chuàng)建美式咖啡工廠類 實現(xiàn) 咖啡工廠類接口
public class AmericanCoffeeFactory implements CoffeeFactory {
@Override
public Coffee creatCoffee() {
return new AmericanCoffee();
}
}
最后就是咖啡點通過不同類型創(chuàng)建不同的咖啡伺绽。這個時候看看代碼如下所示:
private void test() {
// 創(chuàng)建咖啡店類對象
CoffeeStore coffeeStore = new CoffeeStore();
//創(chuàng)建拿鐵咖啡工廠养泡,多態(tài)
CoffeeFactory coffeeFactory = new LatteCoffeeFactory();
//CoffeeFactory amerFactory = new AmericanCoffeeFactory();
coffeeStore.setCoffeeFactory(coffeeFactory);
// 點咖啡
Coffee coffee = coffeeStore.orderCoffee();
System.out.println(coffee.getName());
}
//咖啡店類
public class CoffeeStore {
private CoffeeFactory coffeeFactory;
public void setCoffeeFactory(CoffeeFactory coffeeFactory) {
this.coffeeFactory = coffeeFactory;
}
public Coffee orderCoffee(){
// 咖啡工廠來創(chuàng)建具體的咖啡
Coffee coffee = coffeeFactory.creatCoffee();
// 加配料
coffee.addMilk();
coffee.addSugar();
return coffee;
}
}
3.5 工廠方法分析
工廠方法模式是簡單工廠模式的進一步抽象和推廣。由于使用了面向?qū)ο蟮亩鄳B(tài)性奈应,工廠方法模式保持了簡單工廠模式的優(yōu)點澜掩,而且克服了它的缺點。
在工廠方法模式中杖挣,核心的工廠類不再負責所有產(chǎn)品的創(chuàng)建肩榕,而是將具體創(chuàng)建工作交給子類去做。這個核心類僅僅負責給出具體工廠必須實現(xiàn)的接口惩妇,而不負責哪一個產(chǎn)品類被實例化這種細節(jié)株汉,這使得工廠方法模式可以允許系統(tǒng)在不修改工廠角色的情況下引進新產(chǎn)品。
在工廠方法模式中歌殃,工廠方法用來創(chuàng)建客戶所需要的產(chǎn)品乔妈,同時還向客戶隱藏了哪種具體產(chǎn)品類將被實例化這一細節(jié),用戶只需要關心所需產(chǎn)品對應的工廠氓皱,無須關心創(chuàng)建細節(jié)路召,甚至無須知道具體產(chǎn)品類的類名勃刨。
使用工廠方法模式的另一個優(yōu)點是在系統(tǒng)中加入新產(chǎn)品時,無須修改抽象工廠和抽象產(chǎn)品提供的接口股淡,無須修改客戶端身隐,也無須修改其他的具體工廠和具體產(chǎn)品,而只要添加一個具體工廠和具體產(chǎn)品就可以了唯灵。這樣贾铝,系統(tǒng)的可擴展性也就變得非常好,完全符合“開閉原則”埠帕。
3.6 工廠方法場景
在以下情況下可以使用工廠方法模式:
- 一個類不知道它所需要的對象的類:在工廠方法模式中垢揩,客戶端不需要知道具體產(chǎn)品類的類名,只需要知道所對應的工廠即可搞监,具體的產(chǎn)品對象由具體工廠類創(chuàng)建水孩;客戶端需要知道創(chuàng)建具體產(chǎn)品的工廠類。
- 一個類通過其子類來指定創(chuàng)建哪個對象:在工廠方法模式中琐驴,對于抽象工廠類只需要提供一個創(chuàng)建產(chǎn)品的接口俘种,而由其子類來確定具體要創(chuàng)建的對象,利用面向?qū)ο蟮亩鄳B(tài)性和里氏代換原則绝淡,在程序運行時宙刘,子類對象將覆蓋父類對象,從而使得系統(tǒng)更容易擴展牢酵。
- 將創(chuàng)建對象的任務委托給多個工廠子類中的某一個悬包,客戶端在使用時可以無須關心是哪一個工廠子類創(chuàng)建產(chǎn)品子類,需要時再動態(tài)指定馍乙,可將具體工廠類的類名存儲在配置文件或數(shù)據(jù)庫中布近。
3.7 工廠方法不足
在添加新產(chǎn)品時,需要編寫新的具體產(chǎn)品類丝格,而且還要提供與之對應的具體工廠類撑瞧,系統(tǒng)中類的個數(shù)將成對增加,在一定程度上增加了系統(tǒng)的復雜度显蝌,有更多的類需要編譯和運行预伺,會給系統(tǒng)帶來一些額外的開銷。
由于考慮到系統(tǒng)的可擴展性曼尊,需要引入抽象層酬诀,在客戶端代碼中均使用抽象層進行定義,增加了系統(tǒng)的抽象性和理解難度骆撇,且在實現(xiàn)時可能需要用到DOM瞒御、反射等技術,增加了系統(tǒng)的實現(xiàn)難度艾船。
04.抽象工廠介紹
4.1 抽象工廠背景
在工廠方法模式中具體工廠負責生產(chǎn)具體的產(chǎn)品葵腹,每一個具體工廠對應一種具體產(chǎn)品高每,工廠方法也具有唯一性屿岂,一般情況下践宴,一個具體工廠中只有一個工廠方法或者一組重載的工廠方法。但是有時候我們需要一個工廠可以提供多個產(chǎn)品對象爷怀,而不是單一的產(chǎn)品對象阻肩。
當系統(tǒng)所提供的工廠所需生產(chǎn)的具體產(chǎn)品并不是一個簡單的對象,而是多個位于不同產(chǎn)品等級結(jié)構(gòu)中屬于不同類型的具體產(chǎn)品時需要使用抽象工廠模式运授。
抽象工廠模式與工廠方法模式最大的區(qū)別在于烤惊,工廠方法模式針對的是一個產(chǎn)品等級結(jié)構(gòu),而抽象工廠模式則需要面對多個產(chǎn)品等級結(jié)構(gòu)吁朦,一個工廠等級結(jié)構(gòu)可以負責多個不同產(chǎn)品等級結(jié)構(gòu)中的產(chǎn)品對象的創(chuàng)建柒室。
4.2 抽象工廠定義
抽象工廠模式(Abstract Factory Pattern):提供一個創(chuàng)建一系列相關或相互依賴對象的接口,而無須指定它們具體的類逗宜。抽象工廠模式又稱為Kit模式雄右,屬于對象創(chuàng)建型模式。
4.3 抽象工廠結(jié)構(gòu)
抽象工廠模式包含如下角色:
- AbstractFactory:抽象工廠纺讲。提供了創(chuàng)建產(chǎn)品的接口擂仍,它包含多個創(chuàng)建產(chǎn)品的方法,可以創(chuàng)建多個不同等級的產(chǎn)品熬甚。
- ConcreteFactory:具體工廠逢渔。主要是實現(xiàn)抽象工廠中的多個抽象方法,完成具體產(chǎn)品的創(chuàng)建乡括。
- AbstractProduct:抽象產(chǎn)品肃廓。定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能诲泌,抽象工廠模式有多個抽象產(chǎn)品盲赊。
- Product:具體產(chǎn)品。實現(xiàn)了抽象產(chǎn)品角色所定義的接口档礁,由具體工廠來創(chuàng)建角钩,它 同具體工廠之間是多對一的關系。
4.4 抽象工廠案例
后期咖啡點業(yè)務增多呻澜,現(xiàn)在不僅生產(chǎn)咖啡递礼,還要生產(chǎn)甜點,請用抽象工廠去實現(xiàn)咖啡店咖啡和甜點的生產(chǎn)羹幸。
實現(xiàn)咖啡抽象產(chǎn)品和具體產(chǎn)品脊髓,代碼如下:
// 咖啡抽象類
public abstract class Coffee {
public abstract String getName();
public void addMilk(){
System.out.println("加奶...");
}
public void addSugar(){
System.out.println("加糖...");
}
}
// 美式咖啡類 繼承 咖啡類
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
public void show() {
System.out.println("我是美式咖啡....");
}
}
// 拿鐵咖啡類 繼承 咖啡類
public class LatteCoffee extends Coffee {
@Override
public String getName() {
return "拿鐵咖啡";
}
}
實現(xiàn)甜品抽象產(chǎn)品和具體產(chǎn)品,代碼如下:
// 抽象甜品類
public abstract class Dessert {
// 定義展示具體甜品的規(guī)范
public abstract void show();
}
// 具體甜品--提拉米蘇類 繼承 抽象甜品類
public class Tiramisu extends Dessert{
@Override
public void show() {
System.out.println("提拉米蘇...");
}
}
// 具體甜品--抹茶慕斯類 繼承 抽象甜品類
public class MatchaMousse extends Dessert {
@Override
public void show() {
System.out.println("抹茶慕斯...");
}
}
抽象工廠栅受,這個時候則需要抽象出生產(chǎn)甜品将硝,生產(chǎn)咖啡的接口恭朗。代碼如下所示
//抽象工廠 生產(chǎn)咖啡類 生產(chǎn)甜品類
public interface DessertFactory {
// 生產(chǎn)咖啡
Coffee createCoffee();
// 生產(chǎn)甜品
Dessert createDessert();
}
具體工廠,分別實現(xiàn)生產(chǎn)甜品的具體工廠依疼,生產(chǎn)咖啡的具體工廠痰腮。代碼如下所示
// 意大利風味甜品工廠
// 生產(chǎn)拿鐵咖啡和提拉米蘇甜品
public class ItalyDessertFactory implements DessertFactory{
// 生產(chǎn)拿鐵咖啡
@Override
public Coffee createCoffee() {
return new LatteCoffee();
}
// 生產(chǎn)提拉米蘇
@Override
public Dessert createDessert() {
return new Tiramisu();
}
}
// 美式風味的甜品工廠
// 生美式咖啡 和 抹茶慕斯
public class AmericanDessertFactory implements DessertFactory{
// 生產(chǎn)美式咖啡
@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}
// 生產(chǎn)抹茶慕斯
@Override
public Dessert createDessert() {
return new MatchaMousse();
}
}
最后就是咖啡點通過不同類型創(chuàng)建不同的咖啡,也可以點不同類型的甜品律罢。這個時候看看代碼如下所示:
private void test() {
// 創(chuàng)建意大利風味甜品工廠對象
// 該工廠生產(chǎn)拿鐵咖啡 和提拉米蘇
ItalyDessertFactory factory = new ItalyDessertFactory();
// 獲取拿鐵咖啡
Coffee coffee = factory.createCoffee();
System.out.println(coffee.getName());//拿鐵咖啡
// 獲取提拉米蘇
Dessert dessert = factory.createDessert();
dessert.show();//提拉米蘇...
// 創(chuàng)建美式風味的甜品工廠對象
//該工廠生產(chǎn)美式咖啡 和抹茶慕斯
AmericanDessertFactory factory1 = new AmericanDessertFactory();
// 獲取美式咖啡
Coffee coffee1 = factory1.createCoffee();
System.out.println(coffee1.getName());//美式咖啡
// 獲取抹茶慕斯
Dessert dessert1 = factory1.createDessert();
dessert1.show();//抹茶慕斯...
}
思考一下該案例
- 當一個產(chǎn)品族中的多個對象被設計成一起工作時膀值,它能保證客戶端始終只使用同一個產(chǎn)品族中的對象。
- 當產(chǎn)品族中需要增加一個新的產(chǎn)品時误辑,所有的工廠類都需要進行修改沧踏。
4.5 抽象工廠分析
當一個產(chǎn)品族中的多個對象被設計成一起工作時,它能夠保證客戶端始終只使用同一個產(chǎn)品族中的對象巾钉。這對一些需要根據(jù)當前環(huán)境來決定其行為的軟件系統(tǒng)來說翘狱,是一種非常實用的設計模式。
增加新的具體工廠和產(chǎn)品族很方便砰苍,無須修改已有系統(tǒng)潦匈,符合“開閉原則”。
4.6 抽象工廠場景
在以下情況下可以使用抽象工廠模式:
- 一個系統(tǒng)不應當依賴于產(chǎn)品類實例如何被創(chuàng)建师骗、組合和表達的細節(jié)历等,這對于所有類型的工廠模式都是重要的。
- 系統(tǒng)中有多于一個的產(chǎn)品族辟癌,而每次只使用其中某一產(chǎn)品族寒屯。
- 屬于同一個產(chǎn)品族的產(chǎn)品將在一起使用,這一約束必須在系統(tǒng)的設計中體現(xiàn)出來黍少。
- 系統(tǒng)提供一個產(chǎn)品類的庫寡夹,所有的產(chǎn)品以同樣的接口出現(xiàn),從而使客戶端不依賴于具體實現(xiàn)厂置。
4.7 抽象工廠不足
在添加新的產(chǎn)品對象時菩掏,難以擴展抽象工廠來生產(chǎn)新種類的產(chǎn)品,這是因為在抽象工廠角色中規(guī)定了所有可能被創(chuàng)建的產(chǎn)品集合昵济,要支持新種類的產(chǎn)品就意味著要對該接口進行擴展智绸,而這將涉及到對抽象工廠角色及其所有子類的修改,顯然會帶來較大的不便访忿。
開閉原則的傾斜性(增加新的工廠和產(chǎn)品族容易瞧栗,增加新的產(chǎn)品等級結(jié)構(gòu)麻煩)。
05.工廠模式總結(jié)
5.1 工廠設計總結(jié)
01.工廠模式設計
工廠模式分類海铆,大概分為三種更加細分的類型:簡單工廠迹恐、工廠方法和抽象工廠。一般情況下卧斟,使用簡單工廠殴边,工廠方法場景稍多憎茂。
工廠模式思考,主要要搞清楚應用場景锤岸。什么時候該用工廠模式竖幔?相對于直接 new 來創(chuàng)建對象,用工廠模式來創(chuàng)建究竟有什么好處呢能耻?
思考一個題目赏枚,你要在店里買各種咖啡亡驰,而這些咖啡中有的加冰晓猛,有的加奶,有的加糖凡辱。比如美式咖啡戒职,拿鐵咖啡,摩卡咖啡透乾,巴西咖啡等等洪燥!用簡單工廠,工廠方法乳乌,抽象工廠分別實現(xiàn)捧韵。
02.簡單工廠介紹
一句話概括簡單工廠:可以根據(jù)參數(shù)的不同返回不同類的實例。
簡單工廠模式包含如下角色:抽象產(chǎn)品角色汉操,具體產(chǎn)品角色再来,工廠角色。
簡單工廠實現(xiàn):
- 創(chuàng)造抽象產(chǎn)品角色磷瘤,比如總結(jié)出很多咖啡都可能會芒篷,加糖,加冰采缚,加奶针炉,因此把它抽成抽象方法。
- 具體產(chǎn)品角色扳抽,這塊有:美式咖啡類篡帕,拿鐵咖啡類,摩卡咖啡等贸呢,這些都是具體的咖啡產(chǎn)品镰烧。
- 工廠角色。負責創(chuàng)建不同咖啡贮尉,為了簡便高效地分配咖啡拌滋,設了根據(jù)類型(比如
american
,latte
)來提供不同的咖啡猜谚。
03.工廠方法介紹
工廠方法模式:定義一個創(chuàng)建對象的接口(指的是抽象工廠)败砂,讓子類(具體工廠)決定實例化哪個產(chǎn)品類對象赌渣。工廠方法使一個產(chǎn)品類的實例化延遲到其工廠的子類。
工廠方法實現(xiàn):
- Product:抽象產(chǎn)品昌犹。這個和簡單工廠模式代碼一樣坚芜,忽略!
- ConcreteProduct:具體產(chǎn)品斜姥。這個和簡單工廠模式代碼一樣鸿竖,忽略!
- Factory:抽象工廠铸敏。這塊定義咖啡工廠接口缚忧,通過該接口子類可以自己實現(xiàn)咖啡創(chuàng)建。
- ConcreteFactory:具體工廠杈笔。這里主要是創(chuàng)建美式咖啡工廠類闪水,創(chuàng)建拿鐵咖啡工廠類。
04.抽象工廠介紹
抽象工廠模式:抽象工廠模式是工廠方法模式的升級版本蒙具,工廠方法模式只生產(chǎn)一個等級(即球榆,同種的產(chǎn)品)的產(chǎn)品,而抽象工廠模式可生產(chǎn)多個等級(即禁筏,多種產(chǎn)品)的產(chǎn)品持钉。
抽象工廠實現(xiàn):
- AbstractFactory:抽象工廠。這個時候則需要抽象出生產(chǎn)甜品篱昔,生產(chǎn)咖啡的接口每强。
- ConcreteFactory:具體工廠。分別實現(xiàn)生產(chǎn)甜品的具體工廠旱爆,生產(chǎn)咖啡的具體工廠舀射。
- AbstractProduct:抽象產(chǎn)品。這里把甜點抽象成一個產(chǎn)品怀伦,把咖啡抽象成一個產(chǎn)品脆烟。
- Product:具體產(chǎn)品。創(chuàng)建具體的美式咖啡房待,拿鐵咖啡產(chǎn)品邢羔。創(chuàng)建具體的提拉米蘇甜點,抹茶慕斯甜點桑孩。
5.2 如何選擇
簡單工廠(Simple Factory)模式:
- 定義:簡單工廠模式通過一個工廠類來創(chuàng)建對象拜鹤,根據(jù)傳入的參數(shù)或條件決定創(chuàng)建哪種具體對象。
- 特點:簡單工廠模式只有一個工廠類流椒,根據(jù)條件創(chuàng)建對象敏簿,隱藏了對象的創(chuàng)建細節(jié)。
- 適用場景:當需要根據(jù)條件創(chuàng)建不同類型的對象時,可以考慮使用簡單工廠模式惯裕。
工廠方法(Factory Method)模式:
- 定義:工廠方法模式將對象的創(chuàng)建延遲到子類中温数,每個子類負責創(chuàng)建自己的對象。
- 特點:工廠方法模式通過定義一個抽象的工廠接口和多個具體的工廠類蜻势,每個工廠類負責創(chuàng)建一種具體對象撑刺。
- 適用場景:當需要創(chuàng)建多個相關對象,并且希望將對象的創(chuàng)建邏輯封裝在具體的工廠類中時握玛,可以考慮使用工廠方法模式够傍。
抽象工廠(Abstract Factory)模式:
- 定義:抽象工廠模式提供一個接口,用于創(chuàng)建一系列相關或相互依賴的對象挠铲,而無需指定具體的類冕屯。
- 特點:抽象工廠模式通過定義抽象工廠接口和多個具體工廠類,每個具體工廠類負責創(chuàng)建一組相關的對象市殷。
- 適用場景:當需要創(chuàng)建一系列相關的對象愕撰,并且希望將對象的創(chuàng)建邏輯封裝在具體的工廠類中時,可以考慮使用抽象工廠模式醋寝。
5.3 更多內(nèi)容推薦
模塊 | 描述 | 備注 |
---|---|---|
GitHub | 多個YC系列開源項目越平,包含Android組件庫剃毒,以及多個案例 | GitHub |
博客匯總 | 匯聚Java炸渡,Android教藻,C/C++浙于,網(wǎng)絡協(xié)議锰镀,算法抡秆,編程總結(jié)等 | YCBlogs |
設計模式 | 六大設計原則向族,23種設計模式搀继,設計模式案例窘面,面向?qū)ο笏枷?/td> | 設計模式 |
Java進階 | 數(shù)據(jù)設計和原理,面向?qū)ο蠛诵乃枷脒辞琁O财边,異常,線程和并發(fā)点骑,JVM | Java高級 |
網(wǎng)絡協(xié)議 | 網(wǎng)絡實際案例酣难,網(wǎng)絡原理和分層,Https黑滴,網(wǎng)絡請求憨募,故障排查 | 網(wǎng)絡協(xié)議 |
計算機原理 | 計算機組成結(jié)構(gòu),框架袁辈,存儲器菜谣,CPU設計,內(nèi)存設計,指令編程原理尾膊,異常處理機制甘磨,IO操作和原理 | 計算機基礎 |
學習C編程 | C語言入門級別系統(tǒng)全面的學習教程,學習三到四個綜合案例 | C編程 |
C++編程 | C++語言入門級別系統(tǒng)全面的教學教程眯停,并發(fā)編程济舆,核心原理 | C++編程 |
算法實踐 | 專欄,數(shù)組莺债,鏈表滋觉,棧,隊列齐邦,樹椎侠,哈希,遞歸措拇,查找我纪,排序等 | Leetcode |
Android | 基礎入門,開源庫解讀丐吓,性能優(yōu)化浅悉,F(xiàn)ramework,方案設計 | Android |
23種設計模式
23種設計模式 & 描述 & 核心作用 | 包括 |
---|---|
創(chuàng)建型模式 提供創(chuàng)建對象用例券犁。能夠?qū)④浖K中對象的創(chuàng)建和對象的使用分離 |
工廠模式(Factory Pattern) 抽象工廠模式(Abstract Factory Pattern) 單例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern) |
結(jié)構(gòu)型模式 關注類和對象的組合术健。描述如何將類或者對象結(jié)合在一起形成更大的結(jié)構(gòu) |
適配器模式(Adapter Pattern) 橋接模式(Bridge Pattern) 過濾器模式(Filter、Criteria Pattern) 組合模式(Composite Pattern) 裝飾器模式(Decorator Pattern) 外觀模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) |
行為型模式 特別關注對象之間的通信粘衬。主要解決的就是“類或?qū)ο笾g的交互”問題 |
責任鏈模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解釋器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 備忘錄模式(Memento Pattern) 觀察者模式(Observer Pattern) 狀態(tài)模式(State Pattern) 空對象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 訪問者模式(Visitor Pattern) |