0x01 前言
??繼上一篇文章所述,抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠創(chuàng)建其他工廠降传。該超級工廠又稱為其他工廠的工廠篷朵。這種類型的設(shè)計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式婆排。
??在抽象工廠模式中声旺,接口是負(fù)責(zé)創(chuàng)建一個相關(guān)對象的工廠,不需要顯式指定它們的類段只。每個生成的工廠都能按照工廠模式提供對象腮猖。
0x02 簡介
意圖:提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無需指定它們具體的類赞枕。
主要解決:主要解決接口選擇的問題澈缺。
何時使用:系統(tǒng)的產(chǎn)品有多于一個的產(chǎn)品族坪创,而系統(tǒng)只消費(fèi)其中某一族的產(chǎn)品。
如何解決:在一個產(chǎn)品族里面姐赡,定義多個產(chǎn)品误堡。
關(guān)鍵代碼:在一個工廠里聚合多個同類產(chǎn)品。
應(yīng)用實(shí)例:工作了雏吭,為了參加一些聚會锁施,肯定有兩套或多套衣服吧,比如說有商務(wù)裝(成套杖们,一系列具體產(chǎn)品)悉抵、時尚裝(成套,一系列具體產(chǎn)品)摘完,甚至對于一個家庭來說姥饰,可能有商務(wù)女裝、商務(wù)男裝孝治、時尚女裝列粪、時尚男裝,這些也都是成套的谈飒,即一系列具體產(chǎn)品岂座。假設(shè)一種情況(現(xiàn)實(shí)中是不存在的,要不然杭措,沒法進(jìn)入共產(chǎn)主義了费什,但有利于說明抽象工廠模式),在您的家中手素,某一個衣柜(具體工廠)只能存放某一種這樣的衣服(成套鸳址,一系列具體產(chǎn)品),每次拿這種成套的衣服時也自然要從這個衣柜中取出了泉懦。用 OO 的思想(面向?qū)ο螅┤ダ斫飧迨颍械囊鹿瘢ň唧w工廠)都是衣柜類的(抽象工廠)某一個,而每一件成套的衣服又包括具體的上衣(某一具體產(chǎn)品)崩哩,褲子(某一具體產(chǎn)品)巡球,這些具體的上衣其實(shí)也都是上衣(抽象產(chǎn)品),具體的褲子也都是褲子(另一個抽象產(chǎn)品)琢锋。
優(yōu)點(diǎn):當(dāng)一個產(chǎn)品族中的多個對象被設(shè)計成一起工作時辕漂,它能保證客戶端始終只使用同一個產(chǎn)品族中的對象呢灶。
缺點(diǎn):產(chǎn)品族擴(kuò)展非常困難吴超,要增加一個系列的某一產(chǎn)品,既要在抽象的 Creator 里加代碼鸯乃,又要在具體的里面加代碼鲸阻。
使用場景: 1跋涣、QQ 換皮膚,一整套一起換鸟悴。 2陈辱、生成不同操作系統(tǒng)的程序。
注意事項(xiàng):產(chǎn)品族難擴(kuò)展细诸,產(chǎn)品等級易擴(kuò)展沛贪。
0x03 設(shè)計概述
??抽象工廠模式是工廠方法模式的升級版本,他用來創(chuàng)建一組相關(guān)或者相互依賴的對象震贵。
??抽象工廠模式時代:隨著客戶的要求越來越高利赋,需要定制不同組合的電腦。例如聯(lián)想 Y 系列猩系,華碩 G 系列媚送,聯(lián)想 Y 配備性能級顯卡,聯(lián)想 G 配備發(fā)燒級顯卡寇甸。那么并不需要創(chuàng)辦一個生產(chǎn)聯(lián)想 Y 性能級顯卡電腦的工廠塘偎、華碩 G 發(fā)燒級顯卡電腦的工廠。而僅僅是抽象一個工廠拿霉,用來生產(chǎn)聯(lián)想 Y 電腦吟秩、華碩 G 電腦、性能級顯卡绽淘、發(fā)燒級顯卡峰尝,然后組合就形成產(chǎn)品。
0x04 具體實(shí)現(xiàn)
抽象工廠時代
項(xiàng)目結(jié)構(gòu)圖
產(chǎn)品類
??為產(chǎn)品顯卡創(chuàng)建接口收恢。
// factory_pattern.abstract_factory.product.IGraphics
public interface IGraphics {
void getGraphics(String series);
}
??為產(chǎn)品電腦創(chuàng)建接口武学。
// factory_pattern.abstract_factory.product.IComputer
public interface IComputer {
void getComputer(String brand);
}
??拓展上述接口,采用需要組合的方式生產(chǎn)產(chǎn)品伦意,所以將類進(jìn)行細(xì)分拓展接口火窒。
??拓展顯卡接口 IGraphics
,定義性能級顯卡類 PerformanceGraphics
驮肉。
// factory_pattern.abstract_factory.product.impl.PerformanceGraphics
public class PerformanceGraphics implements IGraphics {
@Override
public void getGraphics(String series) {
System.out.println("研發(fā)一個 " + series + " 顯卡");
}
}
??拓展顯卡接口 IGraphics
熏矿,定義發(fā)燒級顯卡類 FeverGraphics
。
// factory_pattern.abstract_factory.product.impl.FeverGraphics
public class FeverGraphics implements IGraphics {
@Override
public void getGraphics(String series) {
System.out.println("制造一個 " + series + " 顯卡");
}
}
??拓展電腦接口 IComputer
离钝,定義聯(lián)想電腦類 LenovoComputer
票编。
// factory_pattern.abstract_factory.product.impl.LenovoComputer
public class LenovoComputer implements IComputer {
@Override
public void getComputer(String brand) {
System.out.println("制造一臺 " + brand + " 筆記本電腦");
}
}
??拓展電腦接口 IComputer
,定義華碩電腦類 AsusComputer
卵渴。
// factory_pattern.abstract_factory.product.impl.AsusComputer
public class AsusComputer implements IComputer {
@Override
public void getComputer(String brand) {
System.out.println("研發(fā)一臺 " + brand + " 臺式電腦");
}
}
工廠類
??為 Computer 和 Graphics 對象創(chuàng)建接口 IAbstractFactory
來獲取工廠慧域。
// factory_pattern.abstract_factory.factory.IAbstractFactory
public interface IAbstractFactory {
IComputer createComputer(String brand);
IGraphics createGraphics(String series);
}
??創(chuàng)建擴(kuò)展了 IAbstractFactory
的工廠接口,基于給定的信息生成實(shí)體類的對象浪读。
// factory_pattern.abstract_factory.factory.impl.GraphicsFactroy
public class GraphicsFactroy implements IAbstractFactory {
@Override
public IComputer createComputer(String brand) {
return null;
}
@Override
public IGraphics createGraphics(String series) {
switch (series) {
case "Performance" :
return new PerformanceGraphics();
case "Fever" :
return new FeverGraphics();
default :
throw new IllegalArgumentException();
}
}
}
// factory_pattern.abstract_factory.factory.impl.ComputerFactory
public class ComputerFactory implements IAbstractFactory {
@Override
public IComputer createComputer(String brand) {
switch (brand) {
case "Lenovo" :
return new LenovoComputer();
case "Asus" :
return new AsusComputer();
default :
throw new IllegalArgumentException();
}
}
@Override
public IGraphics createGraphics(String series) {
return null;
}
}
??創(chuàng)建一個工廠創(chuàng)造器 / 生成器類昔榴,通過傳遞品牌或型號來獲取工廠辛藻。
// factory_pattern.abstract_factory.factory.impl.FactoryProducer
public class FactoryProducer {
public static IAbstractFactory getFactory(String choice){
switch (choice) {
case "Computer" :
return new ComputerFactory();
case "Graphics" :
return new GraphicsFactroy();
default :
throw new IllegalArgumentException();
}
}
}
用戶類
??使用 FactoryProducer 來獲取 IAbstractFactory,通過傳遞類型信息來獲取實(shí)體類的對象互订。
// factory_pattern.abstract_factory.user.ComputerTest
public class ComputerTest {
@Test
public void testGetLenovoPerformanceComputer() {
IAbstractFactory computerFactory = FactoryProducer.getFactory("Computer");
IComputer lenPC = computerFactory.createComputer("Lenovo");
IAbstractFactory graphicsFactory = FactoryProducer.getFactory("Graphics");
IGraphics lenPer = graphicsFactory.createGraphics("Performance");
lenPC.getComputer("Lenovo");
lenPer.getGraphics("Performance");
}
@Test
public void testGetAsusFeverComputer() {
IAbstractFactory computerFactory = FactoryProducer.getFactory("Computer");
IComputer lenPC = computerFactory.createComputer("Asus");
IAbstractFactory graphicsFactory = FactoryProducer.getFactory("Graphics");
IGraphics lenPer = graphicsFactory.createGraphics("Fever");
lenPC.getComputer("Asus");
lenPer.getGraphics("Fever");
}
}
驗(yàn)證輸出
testGetLenovoPerformanceComputer
制造一臺 Lenovo 筆記本電腦
研發(fā)一個 Performance 顯卡
testGetAsusFeverComputer
研發(fā)一臺 Asus 臺式電腦
制造一個 Fever 顯卡
0x05 總結(jié)
??無論是簡單工廠吱肌,工廠方法模式,還是抽象工廠模式仰禽,他們都屬于工廠模式氮墨,在形式和特點(diǎn)上也是極為相似的,他們的最終目的都是為了解耦吐葵。在使用時勇边,我們不必去在意這個模式到底工廠方法模式還是抽象工廠模式,因?yàn)樗麄冎g的演變常常是令人琢磨不透的折联。經(jīng)常你會發(fā)現(xiàn)粒褒,明明使用的工廠方法模式,當(dāng)新需求來臨诚镰,稍加修改奕坟,加入了一個新方法后,由于類中的產(chǎn)品構(gòu)成了不同等級結(jié)構(gòu)中的產(chǎn)品族清笨,它就變成抽象工廠模式了月杉。而對于抽象工廠模式,當(dāng)減少一個方法使的提供的產(chǎn)品不再構(gòu)成產(chǎn)品族之后抠艾,它就演變成了工廠方法模式苛萎。
??所以,在使用工廠模式時检号,只需要關(guān)心降低耦合度的目的是否達(dá)到了腌歉。