設計模式之抽象工廠模式

小青的麪包店開張了一段時間後,生意穩中有升,但是遠遠沒達到小青的預期,因爲不是所有人都吃麪包,小青就想幹脆也賣披薩試試,這時候,小青發現,如果按照製作麪包的步驟來重新走一遍,確實滿足了開放-封閉的原則,但是呢,從新建立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來創建,這種情況下,我們可以使用配置文件來操作,使程序更具有靈活性,根據用戶輸入的內容來改變實例化的類。

以上內容,整理自劉徑舟,張玉華編著的《設計模式其實很簡單》讀書筆記,歡迎轉載.

發佈了38 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章