小青的麪包店開張了一段時間後,生意穩中有升,但是遠遠沒達到小青的預期,因爲不是所有人都吃麪包,小青就想幹脆也賣披薩試試,這時候,小青發現,如果按照製作麪包的步驟來重新走一遍,確實滿足了開放-封閉的原則,但是呢,從新建立Factory,投入有點太大了。小青覺得自己有必要再想想。這時候,小青突然醒悟過來,爲什麼生產麪包的工廠不也生產披薩呢?大家原料都是差不多的,於是小青我開始重新設計修改代碼。
/**
*
* @author ricardo
* @Time 下午1:44:34
* @Function:工廠接口
*
*/
public interface IFactory {
BreadMaker CreateBread();
Pizzamaker CreatePizza();
}
public class BlackBreadFactory implements IFactory {
@Override
public BreadMaker CreateBread() {
// TODO Auto-generated method stub
return new BlackBread();
}
@Override
public Pizzamaker CreatePizza() {
// TODO Auto-generated method stub
return new BlackPizza();
}
}
public class HoneyBreadFactory implements IFactory {
@Override
public BreadMaker CreateBread() {
// TODO Auto-generated method stub
return new HoneyBread();
}
@Override
public Pizzamaker CreatePizza() {
// TODO Auto-generated method stub
return new HoneyPizza();
}
}
public class WhiteBreadFactory implements IFactory {
@Override
public BreadMaker CreateBread() {
// TODO Auto-generated method stub
return new WhiteBread();
}
@Override
public Pizzamaker CreatePizza() {
// TODO Auto-generated method stub
return new WhitePizza();
}
}
客戶端代碼:
public class Three {
public static void main(String[] args) {
BreadMaker breadMaker;
Pizzamaker pizzamaker;
System.out.println("小青的麪包店開業了!");
System.out.println("顧客要買黑麪包");
IFactory breadFactory = new BlackBreadFactory();
breadMaker = breadFactory.CreateBread();
breadMaker.GetBread();
System.out.println("顧客要蜂蜜燕麥披薩");
breadFactory = new HoneyBreadFactory();
pizzamaker = breadFactory.CreatePizza();
pizzamaker.GetPizza();
}
}
運行截圖:
這樣一來,小青我的麪包店就可以按照客戶需求生產披薩或者麪包了。
這就是一種新的設計模式——抽象工廠模式。GOF對抽象工廠模式的定義是:提供一個創建一系列相關或者相互依賴的接口,而無需指定他們的具體類。
抽象工廠模式適用於:
1.一個系列要獨立於它的產品創建、組合和表示時;
2.一個系統要由多個產品系列中的一個來配置時;
3.要強調一個系列相關的產品對象的設計以便進行聯合使用時;
4.當提供產品庫,而只要顯示它們的接口而不是實現的時候。
其實從麪包店例子可以看出,抽象工廠模式適用於客戶端進場要切換配置(交換產品系列),客戶端通過抽象接口來操作實例,具體的類名不會出現在客戶端中。
但是這樣的抽象工廠模式有個很大的問題,比如現在將蜂蜜燕麥改成奶油,新建工廠類後,每一個曾聲明BreakMaker和PizzaMaker的地方都要進行修改,這代碼量就很龐大了。
public class Three {
public static void main(String[] args) {
BreadMaker breadMaker;
Pizzamaker pizzamaker;
System.out.println("小青的麪包店開業了!");
System.out.println("顧客要買黑麪包");
IFactory breadFactory = new BlackBreadFactory();
breadMaker = breadFactory.CreateBread();
breadMaker.GetBread();
System.out.println("顧客要白巧克力披薩");
try {
Class<?> c = Class.forName("com.factory3.HoneyBreadFactory");
try {
breadFactory = (IFactory)c.newInstance();
pizzamaker = breadFactory.CreatePizza();
pizzamaker.GetPizza();
}catch(Exception e) {
System.out.println("嘿,麪包師還在製作中,稍等喲");
}
}catch(ClassNotFoundException e){
System.out.println("意料之外的問題");
}
}
}
針對這種情況,我們使用反射的方式來創建對象,可以看到使用了字符串com.factory3.HoneyBreadFactory來創建,這種情況下,我們可以使用配置文件來操作,使程序更具有靈活性,根據用戶輸入的內容來改變實例化的類。
以上內容,整理自劉徑舟,張玉華編著的《設計模式其實很簡單》讀書筆記,歡迎轉載.