設計模式(五):抽象工廠方法(多個工廠方法的組合)


一、概述

  抽象工廠模式提供一個接口,用於創建相關或依賴對象的家族,而不需要明確指定具體類。可以理解成是多個工廠方法的組合。

二、解決問題

  在工廠方法模式中,我們的具體創建者每次使用都只能創建一個同類型的對象,假如我們現在需要的是多個不同類型的對象,工廠方法就滿足不了需求了。這時我們可以把多個工廠方法組合到一個類,這就是抽象工廠模式,它就是專門用來創建多個產品,也可以說是創建產品家族的。

三、結構類圖

四、成員角色

  抽象工廠(AbstractFactory):客戶端直接引用,由未實現的工廠方法組成,子類必須實現其工廠方法創建產品家族。

  具體工廠(ConcreteFactory):實現抽象工廠接口,負責實現工廠方法,一個具體工廠可以創建一組產品。

  抽象產品(AbstractProduct):產品家族的父類,由此可以衍生很多子產品。

  具體產品(Product):衍生自抽象產品,由工廠方法直接創建。

五、應用實例

  在工廠方法模式中,我們使用了開燒餅店例子,現在我們讓我們繼續開燒餅店,為了保證燒餅的質量,我們要統一生產工藝,還要對原料做統一供應,防止偷工減料的問題。我們就是使用抽象工廠方法來統一供應原材料的,一起來看看如何做到吧。

  首先創建抽象工廠,也就是原材料工廠

package abstrfactorymethod.pattern;

public interface IngredientFactory {
	public Dough createDough();
	public Sauce createSauce();
	public Vegetable createVegetable();
	public Meat createMeat();
	public Seafood createSeafood();
}

  原材料工廠中涉及很多原材料產品,我們現在創建這些產品,先開始創建抽象產品

  

package abstrfactorymethod.pattern;

//面粉
public interface Dough {
	public String getName();
}

  

package abstrfactorymethod.pattern;

//配料
public interface Sauce {
	public String getName();
}

  

package abstrfactorymethod.pattern;

//蔬菜
public interface Vegetable {
	public String getName();
}

  

package abstrfactorymethod.pattern;

//肉
public interface Meat {
	public String getName();
}

  

package abstrfactorymethod.pattern;

//海鮮
public interface Seafood {
	public String getName();
}

  接着創建所需的具體產品

package abstrfactorymethod.pattern;

public class DBDough implements Dough{
	public DBDough(){
		System.out.println("創建" + getName());
	}
	public String getName() {
		return "東北面粉";
	}
}

  

package abstrfactorymethod.pattern;

public class TomatoSauce implements Sauce{
	public TomatoSauce(){
		System.out.println("創建" + getName());
	}
	public String getName() {
		return "番茄醬";
	}
}

  

package abstrfactorymethod.pattern;

public class Onion implements Vegetable{
	public Onion(){
		System.out.println("創建" + getName());
	}
	public String getName() {
		return "洋蔥";
	}
}

  具體原材料准備好了,我們就可以創建具體工廠了

package abstrfactorymethod.pattern;

public class ShaobingIngredientFactory implements IngredientFactory{

	public Dough createDough() {		
		return new DBDough();//東北面粉
	}

	public Meat createMeat() {
		return null;//暫時不用肉,該接口備用
	}

	public Sauce createSauce() {
		return new TomatoSauce();//番茄醬
	}

	public Seafood createSeafood() {
		return null;//暫時不用海鮮,該接口備用
	}

	public Vegetable createVegetable() {
		return new Onion();//洋蔥
	}
	
}

  有了原材料工廠,可以着手做燒餅了,先創建抽象燒餅

package abstrfactorymethod.pattern;

public abstract class Shaobing {
	//燒餅名稱
	public String name;
	//燒餅用的配料
	public Sauce sauce;
	//面團
	public Dough dough;
	//蔬菜
	public Vegetable vegetable;
	
	//該方法在子類實現,創建所需的原材料
	public abstract void prepare();
	
	//烤燒餅
	public void bake(){
		System.out.println("Bake for 25 minutes at 350C");
	}
	
	//切面團
	public void cut(){
		System.out.println("Cutting the dough into fit slices");
	}
	
	//打包
	public void box(){
		System.out.println("Place shaobing into official box");
	}
}

  創建具體燒餅

package abstrfactorymethod.pattern;

//洋蔥燒餅
public  class OnionShaobing extends Shaobing{

	//原材料 抽象工廠
	IngredientFactory ingredientFactory;
	
	public OnionShaobing(){
		ingredientFactory = new ShaobingIngredientFactory();
	}
	@Override
	public void prepare() {
		System.out.println("洋蔥燒餅開始准備原材料");
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		vegetable = ingredientFactory.createVegetable();
	}

}

  燒餅一切准備就緒,可以開店了

package abstrfactorymethod.pattern;

//廣州燒餅店
public class GZShaobingStore extends ShaobingStore{

	@Override
	public Shaobing createShaobing(String type) {
		Shaobing shaobing = null;
		if("onion".equals(type)){
			shaobing = new OnionShaobing();
		}
		
		return shaobing;
	}
}

  測試燒餅店運行情況

package abstrfactorymethod.pattern;

public class TestShaobingStore {
	public static void main(String[] args){
		//在廣州開一個燒餅店
		ShaobingStore gzStore = new GZShaobingStore();
		//售出一個洋蔥燒餅
		gzStore.orderShaobing("onion");		
	}
}

 運行結果:

 

 

六、優點和缺點

  1、優點

  (1)、允許客戶使用抽象的接口創建一組相關產品,而不需要知道(或者關心)產出的具體產品是什么,這樣客戶就可以從具體的產品中解耦出來。

  (2)、一個具體工廠可以創建多個產品,與工廠方法模式相比,可以少產生具體工廠的類數量。

  (3)、易於交換產品系列,只要更換具體工廠,就可以改變這個產品系列。

  2、缺點

  (1)、抽象工廠是使用組合的方式把工廠方法集合到一個類中,當新增一個產品家族成員時就要修改抽象工廠類及其下面的具體工廠類,所以它的擴展性比較差。

  (2)、每新增一個產品子類都要創建一個類,當產品子類過多時會產生很多類,導致系統復雜性加大。

七、使用場合

  1、當需要創建產品家族,或者需要想讓創建的產品集合起來時使用。

  2、當系列產品不固定,在以后可能會增加整個系列產品時使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM