前言
上一篇介紹簡單工廠模式
的時候提到它對開閉原則
支持的不夠坞嘀,因?yàn)槿绻行碌漠a(chǎn)品加入到系統(tǒng)中去,就需要修改工廠類惊来,就違反了開閉原則
了丽涩,這次介紹的工廠方法模式在保持簡單工廠模式優(yōu)點(diǎn)的前提下,還滿足了開閉原則裁蚁,關(guān)鍵在于它的多態(tài)性矢渊。
正文
工廠方法模式概念
工廠方法模式是類的創(chuàng)建模式,又叫做虛擬構(gòu)造子(Cirtual Constructor)模式或者多態(tài)工廠(Polymorphic Factory)模式枉证。
工廠方法模式的用意是定義一個創(chuàng)建產(chǎn)品對象的工廠接口矮男,將實(shí)際創(chuàng)建工作推遲到子類中。
首先室谚,在工廠方法模式中毡鉴,核心的工廠類不再負(fù)責(zé)所有產(chǎn)品的創(chuàng)建,而是將具體創(chuàng)建的工作交給子類去做.這個核心類則搖身一變秒赤,成為了一個抽象工廠角色猪瞬,僅負(fù)責(zé)給出具體工廠子類必須實(shí)現(xiàn)的接口,而不接觸哪一個產(chǎn)品類應(yīng)當(dāng)被實(shí)例化這種細(xì)節(jié)入篮。
這種進(jìn)一步抽象化的結(jié)果陈瘦,使這種工廠方法模式可以用來予許系統(tǒng)在不修改具體工廠角色的情況下引進(jìn)新的產(chǎn)品,也就遵循了開閉原則崎弃。
工廠方法模式的結(jié)構(gòu)
工廠方法模式的結(jié)構(gòu)圖如下:
從上圖可以看出甘晤, 工廠方法模式涉及到抽象工廠角色,具體工廠角色饲做,抽象產(chǎn)品角色以及具體產(chǎn)品角色等四個角色:
- 抽象工廠角色:擔(dān)任這個角色的是工廠方法模式的核心线婚,它是與應(yīng)用程序無關(guān)的。任何在模式中創(chuàng)建對象的工廠類必須實(shí)現(xiàn)這個接口盆均。
- 具體工廠角色:擔(dān)任這個角色的是實(shí)現(xiàn)了抽象工廠接口的具體Java類塞弊,具體工廠角色含有與應(yīng)用密切相關(guān)的邏輯,并且受到應(yīng)用程序的調(diào)用以創(chuàng)建產(chǎn)品對象泪姨。
- 抽象產(chǎn)品角色:工廠方法模式所創(chuàng)建的對象的超類型游沿,也就是產(chǎn)品對象的共同父類或共同擁有的接口桥狡。
- 具體產(chǎn)品角色:這個角色實(shí)現(xiàn)了抽象產(chǎn)品角色所申明的接口卦绣。工廠方法模式所創(chuàng)建的每一個對象都是某個具體產(chǎn)品角色的實(shí)例。
結(jié)合披薩系統(tǒng)咙崎,用白話文來說就是之前廚師(工廠類)負(fù)責(zé)所有的烤披薩任務(wù)仗处,太累了眯勾。于是招了兩個廚師分別負(fù)責(zé)烤 GreekPizza
披薩和 CheesePizza
披薩,之前的廚師升級為廚師長(抽象工廠類)婆誓,負(fù)責(zé)教那兩位廚師(具體工廠類)烤披薩吃环,自己則不用親自動手烤披薩了。
附上代碼前先來看看完整的類圖:
代碼示例講解
下面是抽象產(chǎn)品的角色Pizza的源代碼:
public abstract class Pizza {
public abstract void prepare();
public abstract void bake();
public abstract void cut();
public abstract void box();
}
下面是具體產(chǎn)品角色CheesePizza的源代碼:
public class CheesePizza extends Pizza{
public void prepare(){
System.out.println("準(zhǔn)備CheesePizza~");
}
public void bake(){
System.out.println("正在烤CheesePizza~");
}
public void cut(){
System.out.println("正在切CheesePizza~");
}
public void box(){
System.out.println("正在打包CheesePizza~");
}
}
下面是具體產(chǎn)品角色GreekPizza的源代碼:
public class GreekPizza extends Pizza{
public void prepare(){
System.out.println("準(zhǔn)備GreekPizza~");
}
public void bake(){
System.out.println("正在烤GreekPizza~");
}
public void cut(){
System.out.println("正在切GreekPizza~");
}
public void box(){
System.out.println("正在打包GreekPizza~");
}
}
下面是抽象工廠角色PizzaFactory的代碼,這個角色是使用一個java接口實(shí)現(xiàn)洋幻,它聲明了一個工廠方法郁轻,要求所有的具體工廠角色實(shí)現(xiàn)這個工廠方法:
public interface PizzaFactory {
/**
* 工廠方法
* @return
*/
public Pizza createPizza();
}
下面是具體工廠角色CheesePizzaFactory的代碼,這個角色現(xiàn)實(shí)了抽象工廠角色PizzaFactory所聲明的工廠方法:
public class CheesePizzaFactory implements PizzaFactory{
@Override
public Pizza createPizza() {
return new CheesePizza();
}
}
下面是具體工廠角色GreekPizzaFactory的代碼文留,這個角色現(xiàn)實(shí)了抽象工廠角色PizzaFactory所聲明的工廠方法:
public class GreekPizzaFactory implements PizzaFactory{
@Override
public Pizza createPizza() {
return new GreekPizza();
}
}
下面是客戶端角色的源代碼:
public class OrderPizza {
public static void main(String[] args){
PizzaFactory factory=new CheesePizzaFactory();
Pizza pizza=factory.createPizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
factory=new GreekPizzaFactory();
pizza=factory.createPizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
結(jié)果演示:
準(zhǔn)備CheesePizza~
正在烤CheesePizza~
正在切CheesePizza~
正在打包CheesePizza~
準(zhǔn)備GreekPizza~
正在烤GreekPizza~
正在切GreekPizza~
正在打包GreekPizza~
這里使用工廠方法模式的注意點(diǎn):
** 工廠方法創(chuàng)建對象**:
工廠方法不一定每一次都返還一個新的對象好唯,但是它所返還的對象一定是它自己創(chuàng)建
的。
工廠方法返還的類型:
注意:工廠方法返還的應(yīng)當(dāng)是抽象類型
厂庇,而不是具體類型渠啊,只有這樣才能保證針對產(chǎn)品的多態(tài)性。當(dāng)工廠方法模式發(fā)生上面的退化時权旷,就不再是工廠方法模式了替蛉。
工廠等級結(jié)構(gòu):
工廠對象應(yīng)當(dāng)有一個抽象的超類型。換言之拄氯,應(yīng)當(dāng)有數(shù)個具體工廠類作為一個抽象超類型的具體子類存在于工廠等級結(jié)構(gòu)中躲查。如果等級結(jié)構(gòu)中只有一個具體工程類的話,那么抽象工廠角色也可以省略译柏,這時候镣煮,工廠方法模式就發(fā)生了退化,這一退化表現(xiàn)為針對工廠角色的多態(tài)性的喪失鄙麦。
總結(jié)
工廠方法模式和簡單工廠模式比較:
工廠方法模式跟簡單工廠模式在結(jié)構(gòu)上的不同是很明顯的典唇,工廠方法模式的核心是一個抽象工廠類镊折,而簡單工廠模式的核心在一個具體類。顯而易見工廠方法模式這種結(jié)構(gòu)更好擴(kuò)展介衔,權(quán)力下發(fā)恨胚,分布式比集中式更具優(yōu)勢。
如果系統(tǒng)需要加入一個新的產(chǎn)品炎咖,那么所需要的就是向系統(tǒng)中加入一個這個產(chǎn)品類以及它所對應(yīng)的工廠類赃泡。沒有必要修改客戶端,也沒有必要修改抽象工廠角色或者其他已有的具體工廠角色乘盼。對于增加新的產(chǎn)品類而言升熊,這個系統(tǒng)完全支持開閉原則。
源碼放百度網(wǎng)盤绸栅,有需要自己取级野,對應(yīng)目錄如下
simplefactory:簡單工廠模式
methodFactory:工廠方法模式
AbstractFactory:抽象工廠模式
鏈接:http://pan.baidu.com/s/1kUNygBl
密碼:vc9f
一直覺得自己寫的不是技術(shù),而是情懷粹胯,一篇篇文章是自己這一路走來的痕跡勺阐。靠專業(yè)技能的成功是最具可復(fù)制性的矛双,希望我的這條路能讓你少走彎路渊抽,希望我能幫你抹去知識的蒙塵,希望我能幫你理清知識的脈絡(luò)议忽,希望未來技術(shù)之巔上有你也有我懒闷。