在上一篇文章中工廠模式——簡單工廠模式 我們了解到簡單工廠模式的運用和存在的問題。
回顧下簡單工廠模式里的工廠類寫法:
/**
* 工廠類
*
* @author jinzifu
* @create 2018/2/23 14:41
*/
public class FoodFactory {
/**
* 工廠類靜態(tài)方法
* @param type 產(chǎn)品類型參數(shù)
* @return
*/
public static IMakeFood getInstance(String type) {
IMakeFood iMakeFood = null;
if (type.equalsIgnoreCase("Breakfest")) {
iMakeFood = new Breakfest();
} else if (type.equalsIgnoreCase("Lunch")) {
iMakeFood = new Lunch();
}
return iMakeFood;
}
}
如果新增了一個產(chǎn)品對象,如晚飯。工廠類靜態(tài)方法內(nèi)須增加"else if"方可,這就違背了“開閉原則”,同時也存在如下問題。
- 簡單工廠模式實現(xiàn)了對象的“創(chuàng)建”和“使用”的分離,遵循了“單一職責(zé)原則”,但增加新的產(chǎn)品對象時須修改工廠類靜態(tài)方法,違背了“開閉原則”。
- 工廠類集中了所有產(chǎn)品創(chuàng)建邏輯(幾乎是全能的),一旦不能工作,整個系統(tǒng)影響很大。
- 工廠類中使用了靜態(tài)工廠方法,造成該類方法無法形成基于繼承的等級結(jié)構(gòu)。
工廠方法模式角色分工
工廠方法模式有四部分組成:抽象工廠,具體工廠,抽象產(chǎn)品,具體產(chǎn)品。
- 抽象工廠(AbstractCreator):這個角色的是工廠方法模式的核心,它是與應(yīng)用程序無關(guān)的。在此模式中任何創(chuàng)建對象的工廠類必須繼承此類或者實現(xiàn)此接口。
- 具體工廠(ConcreteCreator):這個角色的是實現(xiàn)了抽象工廠接口的具體Java類。具體工廠角色含有與應(yīng)用密切相關(guān)的邏輯,并且受到應(yīng)用程序的調(diào)用以創(chuàng)建產(chǎn)品對象。
- 抽象產(chǎn)品(AbstractProduct):工廠方法模式所創(chuàng)建的對象的超類型,也就是產(chǎn)品對象的共同父類或共同擁有的接口。在實際應(yīng)用中這個角色常常由Java的抽象類來實現(xiàn)。
- 具體產(chǎn)品(ConcreteProduct):這個角色實現(xiàn)了抽象產(chǎn)品角色所聲明的接口,工廠方法所創(chuàng)建的每一個對象都是某個具體產(chǎn)品角色的實例。
工廠方法模式就是對簡單工廠模式的優(yōu)化,增加的只是抽象工廠這個角色,之前工廠類變?yōu)榫唧w工廠類且移除靜態(tài)工廠方法。
工廠方法模式案例解析
情景:增加了晚飯,做飯變成早飯、午飯、晚飯。
抽象工廠(AbstractCreator)用以被具體工廠繼承父類或?qū)崿F(xiàn)共有接口的。如:
/**
* 抽象工廠-什么飯
*
* @author jinzifu
* @create 2018/2/22 17:54
*/
public interface IFoodFactory {
/**
* 獲取餐類
*
* @return
*/
IMakeFood getFood();
}
和簡單工廠模式里一樣,工廠類最終獲取的是具體產(chǎn)品對象實例,且該產(chǎn)品對象實例是統(tǒng)一實現(xiàn)抽象產(chǎn)品接口或繼承抽象產(chǎn)品類的。這里返回的是實現(xiàn)了IMakeFood接口的對象實例。
具體工廠(ConcreteCreator)用于實現(xiàn)需求指定的產(chǎn)品實例,且具體工廠均實現(xiàn)抽象工廠接口或繼承抽象工廠類。如:
/**
* 具體工廠-晚飯
*
* @author jinzifu
* @create 2018/2/23 22:03
*/
public class DinnerFactory implements IFoodFactory {
@Override
public IMakeFood getFood() {
return new Dinner();
}
}
新增的晚飯具體產(chǎn)品類Dinner,如:
/**
* 具體產(chǎn)品-晚飯
*
* @author jinzifu
* @create 2018/2/23 22:04
*/
public class Dinner implements IMakeFood {
@Override
public void makeFood() {
System.out.println("晚飯");
}
}
外部測試及打印,如:
DinnerFactory dinnerFactory = new DinnerFactory();
Dinner dinner = (Dinner) dinnerFactory.getFood();
dinner.makeFood();
晚飯
工廠方法模式總結(jié)
- 在工廠方法模式下,如果要增加產(chǎn)品,只需要擴展對應(yīng)的具體工廠(ConcreteCreator)和具體產(chǎn)品(ConcreteProduct)即可,原有源碼無需改變,遵循了“開閉原則”。
- 工廠類變?yōu)閷崿F(xiàn)類統(tǒng)一抽象工廠接口或繼承抽象工廠類的具體工廠,具體的產(chǎn)品對象由具體工廠類創(chuàng)建,功能單一,不再臃腫。
- 具體工廠內(nèi)部不再是靜態(tài)工廠方法,且可繼承抽象工廠類,可形成基于繼承的等級結(jié)構(gòu)。
- 每次增加具體產(chǎn)品時,具體工廠類和具體產(chǎn)品類都要增加,文件數(shù)成對出現(xiàn)增加了編譯成本。
作為一種創(chuàng)建類模式,在需要生成復(fù)雜對象的地方,都可以考慮使用工廠模式。而工廠方法模式適用最廣。