除了使用new操作符之外颅围,還有更多制造對象的方法髓抑。你講了解到實例化這個活動不應(yīng)該總是公開的進(jìn)行,也會認(rèn)識到初始化經(jīng)常造成“耦合”問題。你將了解工廠模式如何從復(fù)雜的依賴中幫你脫困鼠冕。
當(dāng)看到new,就會想到具體 所以用的的確是實現(xiàn)胯盯,而不是接口懈费。
new 有什么不對勁?
在技術(shù)上博脑,new沒有錯憎乙,畢竟這是java的基礎(chǔ)部分。真正的犯人是我們的老朋友“改變”叉趣,以及踏實如何影響new的使用的泞边。
針對接口編程,可以隔離掉以后系統(tǒng)可能發(fā)生的一大堆改變疗杉,為什么呢阵谚?如果代碼是針對接口而寫,那么通過多態(tài)烟具,他可以與任何新類 實現(xiàn)該接口梢什。但是,當(dāng)代碼使用大量的具體類時朝聋,等于是自找麻煩绳矩,因為一旦加入新的具體類,就必須改變代碼玖翅。也就是說你的代碼并非“對修改關(guān)閉”翼馆。想用新的具體類型來擴(kuò)展代碼,必須重新打開它金度。
記住应媚,這個設(shè)計應(yīng)該 對擴(kuò)展開放對修改關(guān)閉
如何將實例化具體類的代碼從應(yīng)用中抽離,或者封裝起來猜极,使它們不會干擾應(yīng)用的其他部分中姜?
識別變化的方面
披薩店
Pizza orderPizza(){
//為了讓系統(tǒng)有彈性,我們希望這是一個抽象類或接口跟伏。但如果這樣丢胚,這些類或接口就無法直接實例化。
Pizza pizza = new Pizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
但是你需要更多披薩類型……
所以必須增加一些代碼受扳,來決定適合的披薩類型携龟,然后再“制造”這個披薩。
Pizza orderPizza(String type){
Pizza pizza ;
if(type.equals("cheese")){
pizza=new CheesePizza();
}else if(type.equals("greek")){
pizza=new GreekPizza();
}else if(type.equals("pepperoni")){
pizza=new PepperoniPizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
但是壓力來自于增加更多的披薩類型
你發(fā)現(xiàn)其他餐廳又多了很多流行風(fēng)味的披薩:ClamPizza(蛤蜊披薩)勘高、VeggiePizza(素食披薩)峡蟋。很明顯你要趕上他們坟桅,需要把這些加入你的菜單中,而最近GreekPizza(希臘披薩)賣的不好蕊蝗,所以你決定將它從菜單中去掉:
Pizza orderPizza(String type) {
Pizza pizza;
//這是變化的部分仅乓。隨著時間過去比薩菜單改變,這里就必須一改再改蓬戚。
if (type.equals("cheese")) {
pizza = new CheesePizza();
}
//此代碼沒有對修改封閉夸楣。如果比薩店改變他所供應(yīng)的比薩風(fēng)味,就得進(jìn)到這里來修改子漩。
/*else if (type.equals("greek")) {
pizza = new GreekPizza();
} */else if (type.equals("pepperoni")) {
pizza = new PepperoniPizza();
} else if (type.equals("clam")) {
pizza = new ClamPizza();
} else if (type.equals("veggie")) {
pizza = new VeggiePizza();
}
//這里是我們不想改變的地方裕偿。因為比薩的準(zhǔn)備,烘烤痛单,包裝嘿棘,多年都持續(xù)不變,所以這部分的代碼不會改變旭绒,只是發(fā)生這些動作的比薩會改變鸟妙。
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
很明顯,如果實例化“某些”具體類挥吵,將使orderPizza()出問題重父,而且也無法讓orderPizza()對修改關(guān)閉,但是忽匈,現(xiàn)在我們已經(jīng)知道哪些會改變房午,哪些不會改變,該是使用封裝的時候了丹允。
封裝創(chuàng)建對象的代碼
我們稱這個新對象為“工廠”郭厌。
工廠處理創(chuàng)建對象的細(xì)節(jié)。一旦有了SimplePizzaFactory,orderPizza()就變成此對象的客戶雕蔽。當(dāng)需要比薩時折柠,就叫比薩工程做一個。那些orderPizza()方法需要知道希臘比薩和蛤蜊比薩的日子不去不復(fù)返了∨現(xiàn)在orderPizza()方法只關(guān)心從工廠得到了一個比薩扇售,而這個比薩實現(xiàn)了Pizza接口,所以它可以調(diào)用prepare()嚣艇、bake()邪驮、cut()溃列、box()來分別進(jìn)行準(zhǔn)備暗挑、烘烤蝗肪、切片、裝盒慌洪。
建立一個簡單披薩工廠
//SimplePizzaFactory是新的類顶燕,他只做一件事情:幫它的客戶創(chuàng)建比薩
public class SimplePizzaFactory {
//首先,在這個工廠內(nèi)定義一個createPizza()方法冈爹,所有客戶用這個方法來實例化對象涌攻。
public Pizza createPizza(String type) {
Pizza pizza = null;
if ("cheese".equals(type)) {
} else if ("pepperoni".equals(type)) {
} else if ("clam".equals(type)) {
} else if ("veggie".equals(type)) {
}
return pizza;
}
}
重做PizzaStore類
修改我們的客戶代碼,我們要做的是仰仗工廠來為我們創(chuàng)建披薩频伤。
public class PizzaStore {
//為PizzaStore加上一個對SimplePizzaFactory的引用
SimplePizzaFactory factory;
//PizzaStore的構(gòu)造器恳谎,需要一個工廠作為參數(shù)。
public PizzaStore(SimplePizzaFactory factory) {
this.factory = factory;
}
public Pizza orderPizza(String type) {
Pizza pizza;
//把new操作符替換成工廠對象的創(chuàng)建方法憋肖。這里不再使用具體實例化因痛!
pizza = factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
定義簡單工廠
簡單工廠其實不是一個設(shè)計模式,反而比較像是一種編程習(xí)慣岸更,但由于進(jìn)場被使用鸵膏。所以任務(wù)是工廠模式。
我們來看看新的披薩店類圖:
再次提醒:在設(shè)計模式中怎炊,所謂的“實現(xiàn)一個接口”并“不一定”表示“寫一個類谭企,并利用implement關(guān)鍵詞來實現(xiàn)某個java接口”∑浪粒“實現(xiàn)一個接口”泛指“實現(xiàn)某個超級類型(可以使類或接口)的某個方法
加盟披薩店
你的披薩店經(jīng)營有成债查,擊敗了競爭者,現(xiàn)在大家都希望比薩店能在自己家附加有加盟店瓜挽。每家加盟店都可能想要提供不同風(fēng)味的披薩(紐約盹廷,芝加哥,加州)久橙。
我們已經(jīng)有一個做法……
如果利用SimplePizzaFactory俄占,寫出三種不同的工廠,分別是
NYPizzaFactory淆衷,ChicagoPizzaFactory颠放,CaliforniaPizzaFactory,各地加盟店都有適合的工廠可以使用吭敢,這是一種做法碰凶。
NYPizzaFactory nyFactory=new NYPizzaFactory();
PizzaStore nyStore=new PizzaStore(nyFactory);
nyFactory.orderPizza("Veggie");
但是你想要多一些質(zhì)量控制……
你發(fā)現(xiàn)加盟店確實采用你的工廠創(chuàng)建披薩,但是其他部分鹿驼,卻開始采用他們自創(chuàng)的流程:烘烤的做法有些差異欲低,不要切片,使用其他廠商的盒子畜晰。
在我們稍早的SimplePizzaFactory代碼之前砾莱,制作披薩的代碼綁在PizzaStore里,但是這么做卻沒有彈性凄鼻,那么腊瑟,該怎么辦聚假。
給披薩店使用的框架
有個做法可讓披薩制作局限于PizzaStore類,而同時又能讓這些加盟店依然可以自由地制作該區(qū)域的風(fēng)味闰非。
所要做的事情膘格,就是把createPizza()方法放回到PizzaStore中,不過要把它設(shè)置成“抽象方法”财松,然后為每個區(qū)域風(fēng)味創(chuàng)建一個PizzaStore的子類瘪贱。
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
//現(xiàn)在createPizza()方法從工廠對象中移回PizzaStore
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
//在PizzaStore里,“工廠方法”現(xiàn)在是抽象的辆毡。
abstract Pizza createPizza(String type);
}
現(xiàn)在已近有一個PizzaStore作為超類菜秦,讓每個域類型(NYPizzaFactory,ChicagoPizzaFactory舶掖,CaliforniaPizzaFactory)都繼承這個PizzaStore球昨,每個子類各自決定如何制造披薩,
允許子類做決定
別忘了眨攘,PizzaStore已經(jīng)有一個不錯的訂單系統(tǒng)褪尝,由orderPizza()方法負(fù)責(zé)處理訂單,我們現(xiàn)在要讓createPizza()能夠應(yīng)對這些變化來負(fù)責(zé)創(chuàng)建正確種類的披薩期犬,做法是讓PizzaStore的各個子類負(fù)責(zé)定義自己的createPizza()方法河哑,所以我們會得到一些PizzaStore具體的子類,每個子類都有自己的披薩變體龟虎,而任然適合PizzaStore框架璃谨,并使用調(diào)試好的orderPizza()方法。
讓我們開家比薩店吧
紐約風(fēng)味店:
//NyPizzaStore擴(kuò)展自PizzaStore鲤妥,所以擁有orderPizza()方法(以及其他方法)佳吞。
public class NyPizzaStore extends PizzaStore {
//createPizza()返回一個Pizza對象,由子類全權(quán)負(fù)責(zé)該實例化哪個具體Pizza
//必須實現(xiàn)createPizza()方法棉安,因為在PizzaStore里他是抽象的底扳。
@Override
Pizza createPizza(String type) {
Pizza pizza = null;
if ("cheese".equals(type)) {
} else if ("pepperoni".equals(type)) {
} else if ("clam".equals(type)) {
} else if ("veggie".equals(type)) {
}
return pizza;
}
}
披薩類:
public class Pizza {
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();
public void prepare() {
System.out.println("Preparing " + name);
System.out.println("Tossing dough...");
System.out.println("Addubg sauce...");
System.out.println("Addubg toppings...");
for (int i = 0; i < toppings.size(); i++) {
System.out.println(" " + toppings.get(i));
}
}
public void bake() {
System.out.println("Bake for 25 minutes at 350");
}
public void cut() {
System.out.println("Cuting the pizza into diagonal slices");
}
public void box() {
System.out.println("Place pizza in official PizzaStore box");
}
public String getName() {
return name;
}
}
我們需要一些具體子類,來定義紐約和芝加哥風(fēng)味的芝士披薩贡耽。
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = "NY Style Sauce and Cheese Pizza";
dough = "Thin Crust Dough";
sauce = "Marinara Sauce";
toppings.add("Grated Reggiano Cheese");
}
}
public class ChicagoStyleCheesePizza extends Pizza {
public ChicagoStyleCheesePizza() {
name = "Chicago Style Deep Dish Cheese Pizza";
dough = "Extra Thick Crust Dough";
sauce = "Plum Tomato Sauce";
toppings.add("Shredded Mozzarella Cheese");
}
@Override
public void cut() {
//這里覆蓋了cut()方法 將比薩切成正方形
System.out.println("Cutting the pizza into square slices");
}
}
你已經(jīng)等得夠久了衷模,來吃些披薩吧
PizzaStore pizzaStore = new NyPizzaStore();
Pizza pizza = pizzaStore.orderPizza("cheese");
System.out.println("Ethan ordered a"+pizza.getName()+"\n");
認(rèn)識工廠方法模式的時候終于到了
所有工廠模式都用來封裝對象的創(chuàng)建。工廠方法模式通過讓子類決定該創(chuàng)建的對象是什么蒲赂,來達(dá)到將對象創(chuàng)建的過程封裝的目的阱冶。看看類圖:
另一個觀點:平行的類層級
定義工廠方法模式
工廠方法模式定義了一個創(chuàng)建對象的接口滥嘴,但由子類決定要實例化的類是哪一個木蹬。工廠方法讓類吧實例化推遲到子類。
工廠模式類圖
工廠方法模式能夠封裝具體類型的實例化若皱,抽象的Creator提供了一個創(chuàng)建對象的方法的接口镊叁,在抽象的Creator中尘颓,任何其他實現(xiàn)的方法,都可能使用到這個工廠方法所制造出來的產(chǎn)品晦譬,但只有子類真正實現(xiàn)這個工廠方法并創(chuàng)建產(chǎn)品疤苹。
看看對象依賴
當(dāng)你直接實例化一個對象時,就是在依賴它的具體類蛔添,返回前頁看看這個依賴性很高的比薩店例子痰催,它由披薩店類來創(chuàng)建所有的披薩對象兜辞,而不是委托給工廠迎瞧。
設(shè)計原則
依賴倒置原則 要依賴抽象,不要依賴具體類逸吵。
首先凶硅,這個原則聽起來很像是“針對接口編程,不針對實現(xiàn)編程”扫皱,不是嗎足绅?的確很相似,然而這里更強(qiáng)調(diào)“抽象”韩脑。這個原則說明了:不能讓高層組件依賴底層組件氢妈,而且,不管高層或底層組件段多,兩者都應(yīng)該依賴抽象首量。
讓我們看前面,PizzaStore是“高層組件”进苍,而披薩實現(xiàn)是“底層組件”很清楚地加缘,PizzaStore依賴這些具體披薩類。
現(xiàn)在這個原則告訴我們觉啊,應(yīng)該重寫代碼以便于我們依賴抽象類拣宏,而不依賴具體類。對于高層及底層模塊都應(yīng)該如此杠人。
依賴倒置原則勋乾,究竟倒置在哪里?
在依賴倒置原則中的倒置指的是和一般OO設(shè)計的思考方式完全相反嗡善。
你會注意到前面的底層主鍵現(xiàn)在竟然依賴高層的抽象市俊。同樣的,高層組件現(xiàn)在也依賴相同的抽象滤奈。
倒置你的思考方式
1摆昧、好的,所以你需要試下一個比薩店,你第一件想到的事情是什么蜒程?
嗯绅你!比薩店進(jìn)行準(zhǔn)備伺帘、烘烤、裝盒忌锯、所以我的店必須能制作許多不同風(fēng)味的比薩伪嫁,例如:芝士比薩、素食比薩偶垮、蛤蜊比薩张咳。。似舵。
2脚猾、沒錯!先從頂端開始砚哗,然后往下倒具體類龙助。但是,正如你所看到的你不想讓比薩理會這些具體類蛛芥,要不然比薩店將全都依賴這些具體類√崮瘢現(xiàn)在 倒置 你的想法 、仅淑、称勋、 別從頂端開始,而是從比薩Pizza 開始涯竟,然后想想看能抽象化些什么赡鲜?
是的 芝士比薩、素食比薩昆禽、蛤蜊比薩都是比薩蝗蛙,所以應(yīng)該共享一個Pizza接口。
對了 你想要抽象化一個Pizza醉鳖。
3捡硅、很接近了,但是要這么做盗棵,必須靠一個工廠來經(jīng)這些具體類取出比薩店壮韭。一旦你這么做了,各種不同的具體比薩類型就只能依賴一個抽象纹因,二比薩店也會一來這個抽象喷屋。我們已經(jīng)倒置了一個商店依賴具體類的設(shè)計,而且也倒置了你的思考方式瞭恰。
既然我已經(jīng)有一個比薩抽象屯曹,就可以開始設(shè)計比薩店,而不用理會具體的比薩類了。
下面的指導(dǎo)方針恶耽,能避免在OO設(shè)計中違反依賴倒置原則:
1密任、變量不可以持有具體類的引用。
如果使用new偷俭,就會持有具體類的引用浪讳,你可以改用工廠來避開這樣的做法。
2涌萤、不要讓類派生自具體類淹遵。
如果派生自具體類,你就會以來具體類负溪。請派生自一個抽象(接口或抽象類)透揣。
3、不要覆蓋基類中已實現(xiàn)的方法笙以。
如果覆蓋基類已實現(xiàn)的方法淌实,那么你的基類就不是一個真正適合被繼承的抽象冻辩〔螅基類中已實現(xiàn)的方法,應(yīng)該有所有的子類共享恨闪。
再回到比薩店
有些家門店使用低價原料來增加利潤倘感。必須采取一些手段,確保原料的一致
打算建造一家生產(chǎn)原料的工廠咙咽,并將原料運送到各家加盟店老玛。對于這個做法,現(xiàn)在還剩下一個問題钧敞。家門店坐落在不同的區(qū)域蜡豹,紐約的紅醬料和芝加哥的紅醬料是不一樣的。所以對于紐約和芝加哥溉苛,你準(zhǔn)備兩組不同的原料镜廉。
建造原料工廠
//這個接口負(fù)責(zé)創(chuàng)建所有的原料
public interface PizzaIngredientFactory {
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();
//這里有許多類,每個原料都是一個類
//在接口中愚战,每個原料都有一個對應(yīng)的方法創(chuàng)建該原料
//如果每個工廠實例內(nèi)部都有某一種通用的機(jī)制需要實現(xiàn)娇唯,就可以吧這個例子改寫成抽象類
}
要做的事情是:
1.為每個區(qū)域建造一個工廠,你需要創(chuàng)建一個繼承自PizzaIngredientFactory的子類來實現(xiàn)每一個創(chuàng)建方法寂玲。
2.實現(xiàn)一組原料類供工廠使用塔插,例如ReggianoCheese,RedPeppers,ThickCrustDough.這些類可以在何時的區(qū)域間共享拓哟。
3.然后你仍然需要將這一切組織起來想许,將新的原料工廠整合進(jìn)舊的PizzaStore代碼中。
創(chuàng)建紐約原料工廠
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
@Override
public Dough createDough() {
return new ThinCurstDough();
}
@Override
public Sauce createSauce() {
return new MarinaraSauce();
}
@Override
public Cheese createCheese() {
return new ReggianoCheese();
}
@Override
public Veggies[] createVeggies() {
Veggies veggies[] = {new Garlic(),
new Onion(),
new Mushroom(),
new RedPepper()};
return veggies;
}
@Override
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
@Override
public Clams createClam() {
return new FreshClams();
}
}
重做比薩。流纹。谎砾。
工廠已經(jīng)一切就緒,準(zhǔn)備生產(chǎn)高質(zhì)量原料了捧颅,現(xiàn)在我們只需要重做比薩景图,好讓它們使用工廠生產(chǎn)出來的原料。先從抽象的Pizza類開始:
public abstract class Pizza {
String name;
Dough dough;
Sauce sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clams;
abstract void prepare();
void bake() {
System.out.println("Back for 25 minutes at 350");
}
void cut() {
System.out.println("Cutting the pizza into diagonal slices");
}
void box() {
System.out.println("Place pizza in official PizzaStore box");
}
public String getName() {
return name;
}
void setName(String name) {
this.name = name;
}
public String printString() {
//這里打印披薩的代碼
return "";
}
}
繼續(xù)重做比薩
現(xiàn)在已經(jīng)有一個抽象比薩碉哑,可以開始創(chuàng)建紐約和芝加哥風(fēng)味的比薩了 挚币。從今以后家門店必須直接從工廠取得原料。
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
//要制作比薩扣典,需要工廠提供原料妆毕。所以每個比薩類都需要從構(gòu)造器參數(shù)中得到一個工廠,并把這個工廠存儲在一個實例中
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
@Override
void prepare() {
System.out.println("Preparing " + getName());
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
//Pizza的代碼利用相關(guān)的工廠生產(chǎn)原料贮尖。所生產(chǎn)的原料依賴所使用的工廠笛粘,
// Pizza類根本不關(guān)心這些原料,他只知道如何制作比薩湿硝。
// 現(xiàn)在薪前,Pizza和區(qū)域原料之間被解耦,無論原料工廠是在洛基山脈還是西北沿岸地區(qū)关斜,Pizza類都可以輕易地復(fù)用完全沒問題示括。
// sauce = ingredientFactory.createSauce();
//sauce:把pizza的實例變量設(shè)置為此比薩所使用的某種醬料
//ingredientFactory:這是原料工廠,pizza不在乎使用什么工廠痢畜,只要是原料工廠就行了垛膝。
//createSauce():方法會返回這個區(qū)域所使用的醬料。如果這是一個紐約原料工廠丁稀,我們將取得大蒜番茄醬料
再回到比薩店
public class NYPizzaStore extends PizzaStore {
@Override
Pizza createPizza(String type) {
Pizza pizza = null;
//紐約店會用到紐約比薩原料工廠吼拥,由該原料工廠負(fù)責(zé)生產(chǎn)所有紐約風(fēng)味比薩所需的原料。
PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
if (type.equals("cheese")) {
//把工廠傳遞給每一個比薩线衫,以便比薩能從工廠中取得原料凿可。
pizza = new CheesePizza(ingredientFactory);
pizza.setName("New York Style Cheese PizzaOld");
} else if (type.equals("veggies")) {
pizza = new VeggiePizza(ingredientFactory);
pizza.setName("New York Style Veggies PizzaOld");
} else if (type.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
pizza.setName("New York Style Clam PizzaOld");
}
return pizza;
}
}
一連串的代碼改變;我們到底做了些什么桶雀?
我們引入新類型的工廠矿酵,也就是所謂的抽象工廠,來創(chuàng)建比薩原料家族矗积。
通過抽象工廠所提供的接口全肮,可以創(chuàng)建產(chǎn)品的家族,利用這個接口書寫代碼棘捣,我們的代碼將從實際工廠解耦辜腺,以便在不同上下文中實現(xiàn)各式各樣的工廠,制造出各種不同的產(chǎn)品。例如:不同的區(qū)域评疗,不同的操作系統(tǒng)测砂,不同的外觀及操作。
因為代碼從實際的產(chǎn)品中解耦了百匆,所以我們可以替換不同的工廠來取得不同的行為(例如:取得大蒜番茄醬料砌些,而不是取得番茄醬料)。
定義抽象工廠模式
抽象工廠模式提供一個接口加匈,用于創(chuàng)建相關(guān)或依賴對象的家族存璃,而不需要明確指定具體類。
抽象工廠允許客戶使用抽象的接口來創(chuàng)建一組相關(guān)的產(chǎn)品雕拼,而不需要知道(或關(guān)心)實際產(chǎn)出的具體產(chǎn)品是什么纵东,這樣一來,客戶就從具體的產(chǎn)品中被解耦啥寇。
這是一張更復(fù)雜的類圖偎球,讓我們從PizzaStore的觀點來看一看它:
原則 依賴倒置原則: 依賴抽象,不要依賴具體類.
抽象工廠模式-----提供一個接口辑甜,用于創(chuàng)建相關(guān)或依賴對象的家族衰絮,而不需要明確指定具體類。
工廠方法模式-----定義了一個創(chuàng)建對象的接口栈戳,但由子類決定要實例化的嘞是哪一個岂傲。工廠方法讓類吧實例化推遲到子類难裆。
要點
- 所有的工廠都是用來封裝對象的創(chuàng)建
- 簡單工廠子檀,雖然不是真正的設(shè)計模式,但仍不失為一個簡單的方法乃戈,可以將客戶長須從具體類解耦
- 工廠方法使用繼承:把對象的創(chuàng)建委托給子類褂痰,子類實現(xiàn)工廠方法來創(chuàng)建對象
- 抽象工廠使用對象組合:對象的創(chuàng)建被實現(xiàn)在工廠接口所暴露出來的方法中
- 所有工廠模式都通過減少應(yīng)用程序和具體類之間的依賴促進(jìn)松耦合
- 工廠方法允許類將實例化延遲到子類進(jìn)行。
- 抽象工廠創(chuàng)建相關(guān)的對象家族症虑,而不需要依賴他們的具體類