1. 程式人生 > >設計模式讀書筆記-----抽象工廠模式

設計模式讀書筆記-----抽象工廠模式

        在工廠方法模式中,我們使用一個工廠建立一個產品,也就是說一個具體的工廠對應一個具體的產品。但是有時候我們需要一個工廠能夠提供多個產品物件,而不是單一的物件,這個時候我們就需要使用抽象工廠模式。

在講解抽象工廠模式之前,我們需要釐清兩個概念:

產品等級結構產品的等級結構也就是產品的繼承結構。例如一個為空調的抽象類,它有海爾空調、格力空調、美的空調等一系列的子類,那麼這個抽象類空調和他的子類就構成了一個產品等級結構。

產品族。產品族是在抽象工廠模式中的。在抽象工廠模式中,產品族是指由同一個工廠生產的,位於不同產品等級結構中的一組產品。比如,海爾工廠生產海爾空調。海爾冰箱,那麼海爾空調則位於空調產品族中。

產品等級結構和產品族結構示意圖如下:


        一、基本定義                                                                                                                   

抽象工廠模式提供一個介面,用於建立相關或者依賴物件的家族,而不需要明確指定具體類。

抽象工廠允許客戶端使用抽象的介面來建立一組相關的產品,而不需要關係實際產出的具體產品是什麼。這樣一來,客戶就可以從具體的產品中被解耦。

        二、模式結構                                                                                                                   

抽象工廠模式的UML結構圖如下:

模式結構說明。

AbstractFactory:抽象工廠。抽象工廠定義了一個介面,所有的具體工廠都必須實現此介面,這個介面包含了一組方法用來生產產品。

ConcreteFactory:具體工廠。具體工廠是用於生產不同產品族。要建立一個產品,客戶只需要使用其中一個工廠完全不需要例項化任何產品物件。

AbstractProduct:抽象產品。這是一個產品家族,每一個具體工廠都能夠生產一整組產品。

Product:具體產品。

        三、模式實現                                                                                                                  

依然是披薩店。為了要保證每家加盟店都能夠生產高質量的披薩,防止使用劣質的原料,我們打算建造一家生產原料的工廠,並將原料運送到各家加盟店。但是加盟店都位於不同的區域,比如紐約、芝加哥。紐約使用一組原料,芝加哥使用另一種原料。在這裡我們可以這樣理解,這些不同的區域組成了原料家族,每個區域實現了一個完整的原料家族。

首先建立一個原料工廠。該工廠為抽象工廠,負責建立所有的原料。

PizzaIngredientFactory.java

public interface PizzaIngredientFactory {
	/*
	 * 在介面中,每個原料都有一個對應的方法建立該原料
	 */
	public Dough createDough();    
	
	public Sauce createSauce();
	
	public Cheese createCheese();
	
	public Veggies[] createVeggies();
	
	public Pepperoni createPepperoni();
	
	public Clams createClams();
}

原料工廠建立完成之後,需要建立具體的原料工廠。該具體工廠只需要繼承PizzaIngredientFactory,然後實現裡面的方法即可。

紐約原料工廠:NYPizzaIngredientFactory.java。

public class NYPizzaIngredientFactory implements PizzaIngredientFactory{

	@Override
	public Cheese createCheese() {
		return new ReggianoCheese();
	}

	@Override
	public Clams createClams() {
		return new FreshClams();
	}

	@Override
	public Dough createDough() {
		return new ThinCrustDough();
	}

	@Override
	public Pepperoni createPepperoni() {
		return new SlicedPepperoni();
	}

	@Override
	public Sauce createSauce() {
		return new MarinaraSauce();
	}

	@Override
	public Veggies[] createVeggies() {
		Veggies veggies[] =  {new Garlic(),new Onion(),new Mushroom(),new RefPepper()};
		return veggies;
	}

}

重新返回到披薩。在這個披薩類裡面,我們需要使用原料,其他方法保持不變,將prepare()方法宣告為抽象,在這個方法中,我們需要收集披薩所需要的原料。

Pizza.java

public abstract class Pizza {
	/*
	 * 每個披薩都持有一組在準備時會用到的原料
	 */
	String name;
	Dough dough;
	Sauce sauce;
	Veggies veggies[];
	Cheese cheese;
	Pepperoni pepperoni;
	Clams clams;
	
	/*
	 * prepare()方法宣告為抽象方法。在這個方法中,我們需要收集披薩所需要的原料,而這些原料都是來自原料工廠
	 */
	abstract void prepare();
	
	void bake(){
		System.out.println("Bake for 25 munites at 350");
	}
	
	void cut(){
		System.out.println("Cutting the pizza into diagonal slices");
	}
	
	void box(){
		System.out.println("Place pizza in official PizzaStore box");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

CheesePizza.java

public class CheesePizza extends Pizza{
	PizzaIngredientFactory ingredientFactory;
	
	/*
	 * 要製作披薩必須要有製作披薩的原料,而這些原料是從原料工廠運來的
	 */
	public CheesePizza(PizzaIngredientFactory ingredientFactory){
		this.ingredientFactory = ingredientFactory;
		prepare();
	}
	
	/**
	 * 實現prepare方法
	 * prepare 方法一步一步地建立芝士比薩,每當需要原料時,就跟工廠要
	 */
	void prepare() {
		System.out.println("Prepareing " + name);
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		cheese = ingredientFactory.createCheese();
	}

}

Pizza的程式碼利用相關的工廠生產原料。所生產的原料依賴所使用的工廠,Pizza類根本不關心這些原料,它只需要知道如何製作披薩即可。這裡,Pizza和區域原料之間被解耦。

ClamPizza.java

public class ClamPizza extends Pizza{
	PizzaIngredientFactory ingredientFactory;
	
	public ClamPizza(PizzaIngredientFactory ingredientFactory){
		this.ingredientFactory = ingredientFactory;
	}
	
	@Override
	void prepare() {
		System.out.println("Prepare " + name);
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		cheese = ingredientFactory.createCheese();
		clams = ingredientFactory.createClams();      
	}

}

做完披薩後,需要關注披薩店了。

在披薩店中,我們依然需要關注原料,當地的披薩店需要和本地的原料工廠關聯起來。

PizzaStore.java

public abstract class PizzaStore {
	public Pizza orderPizza(String type){
		Pizza pizza;
		pizza = createPizza(type);
			
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		
		return pizza;
	}
		
	/*
	* 建立pizza的方法交給子類去實現
	 */
	abstract Pizza createPizza(String type);
}
紐約的披薩店:NYPizzaStore.java
public class NYPizzaStore extends PizzaStore{

	@Override
	Pizza createPizza(String type) {
		Pizza pizza = null;
		//使用紐約的原料工廠
		PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();   
		if("cheese".equals(type)){
			pizza = new CheesePizza(ingredientFactory);
			pizza.setName("New York Style Cheese Pizza");
		}
		else if("veggie".equals(type)){
			pizza = new VeggiePizza(ingredientFactory);
			pizza.setName("New York Style Veggie Pizza");
		}
		else if("clam".equals(type)){
			pizza = new ClamPizza(ingredientFactory);
			pizza.setName("New York Style Clam Pizza");
		}
		else if("pepperoni".equals(type)){
			pizza = new PepperoniPizza(ingredientFactory);
			pizza.setName("New York Style Pepperoni Pizza");
		}
		return pizza;
	}	
}

下圖是上面的UML結構圖。


其中PizzaIngredientFactory是抽象的披薩原料工廠介面,它定義瞭如何生產一個相關產品的家族。這個家族包含了所有制作披薩的原料。

NYPizzaIngredientFactory和ChicagoPizzaIngredientFactory是兩個具體披薩工廠類,他們負責生產相應的披薩原料。

NYPizzaStore是抽象工廠的客戶端。

四、模式優缺點                                                                                                                

優點

1、  抽象工廠隔離了具體類的生成,是的客戶端不需要知道什麼被建立。所有的具體工廠都實現了抽象工廠中定義的公共介面,因此只需要改變具體工廠的例項,就可以在某種程度上改變整個軟體系統的行為。

2、  當一個產品族中的多個物件被設計成一起工作時,它能夠保證客戶端始終只使用同一個產品族中的物件。

缺點

新增新的行為時比較麻煩。如果需要新增一個新產品族物件時,需要更改介面及其下所有子類,這必然會帶來很大的麻煩。

五、模式使用場景                                                                                                          

1.  一個系統不應當依賴於產品類例項如何被建立、組合和表達的細節,這對於所有型別的工廠模式都是重要的。

2.系統中有多於一個的產品族,而每次只使用其中某一產品族。

3. 屬於同一個產品族的產品將在一起使用,這一約束必須在系統的設計中體現出來。

4. 系統提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現。

六、總結                                                                                                                        

1、  抽象工廠模式中主要的優點在於具體類的隔離,是的客戶端不需要知道什麼被建立了。其缺點在於增加新的等級產品結構比較複雜,需要修改介面及其所有子類。

相關推薦

設計模式讀書筆記-----抽象工廠模式

        在工廠方法模式中,我們使用一個工廠建立一個產品,也就是說一個具體的工廠對應一個具體的產品。但是有時候我們需要一個工廠能夠提供多個產品物件,而不是單一的物件,這個時候我們就需要使用抽象工

HeadFirst設計模式讀書筆記工廠模式

1. 簡單工廠 1. 你開了一家披薩店,點披薩的方法可能是這樣: public Pizza orderPizza(String type) { Pizza pizza; if (type.equals("芒果披薩")){ pizza = ne

設計模式學習筆記-抽象工廠模式

工廠方法模式是為了克服簡單工廠模式的缺點而設計出來的,簡單工廠模式的工廠類隨著產品類的增加需要增加額外的程式碼),而工廠方法模式每個具體工廠類只完成單個例項的建立,所以它具有很好的可擴充套件性。。但是在現實生活中,一個工廠只建立單個產品這樣的例子很少 定義: 抽象工廠(Abstract Fa

java設計模式學習筆記--抽象工廠模式

1. 什麼是抽象工廠模式 抽象工廠模式提供一個介面,用於建立相關或依賴物件的家族,而不需要明確指定具體類。 也就是說抽象工廠模式是用來 建立產品的家族的。 為了理解這個定義,我們先要搞清楚什麼是產品的家族。 那麼什麼是產品的家族哪,我的理解就是一群相

C#設計模式之四抽象工廠模式(AbstractFactory)【創建型】

抽象 抽象工廠 album 代碼 ctf bst actor 抽象工廠模式 .cn 一、引言 寫了3篇有關設計模式的文章了,大家有了些反饋,說能從中學到一些東西,我感到很欣慰,那就繼續努力。今天我要寫第四個模式了,該模式叫抽象工廠。上一篇文章我們講了【工廠方法】模式,它是為

java設計模式-----3、抽象工廠模式

log 情況下 屬於 運行 title nds 們的 println 支持   抽象工廠模式是所有形態的工廠模式中最為抽象和最具一般性的一種形態。抽象工廠模式是指當有多個抽象角色時,使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個接口,使客戶端在不必指定產品的具體的情況

設計模式學習之抽象工廠模式(Abstract Factory)

轉自:https://blog.csdn.net/u012909091/article/details/38349211 要想正確理解設計模式,首先必須明確它是為了解決什麼問題而提出來的。 ——Shulin 抽象工廠設計模式概念:   &n

經典設計模式(三):抽象工廠模式

抽象工廠模式 本來不想寫這篇文章的,應該是不想寫工廠模式,因為基本大家都會,不過今天看到一個老鐵的部落格,https://www.yuxuan66.com/16 關於抽象模式的實現,寫得不錯,看了幾遍之後,有了點自己的想法,隨便再熟悉一下工廠模式,於是就有了這篇文章,主要是抽象工廠

設計模式篇之抽象工廠模式

抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠建立其他工廠。該超級工廠又稱為其他工廠的工廠。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。 在抽象工廠模式中,介面是負責建立一個相關物件的工廠,不需要顯式指定它們的類。每

HeadFirst設計模式讀書筆記之策略模式

1. 例子 1. 做一個鴨子模擬器,裡面有很多不同的鴨子,有的可以游泳,有的可以睡覺,有的可以呱呱叫,一般套路是定義一個鴨子的超類,在 超類裡定義睡覺,游泳,呱呱叫的方法,再讓不同的鴨子子類繼承這個超類,實現自己的display()方法來表現鴨子的行為,像下面這樣: 2. 但如果要加一個可以吃火鍋的鴨子呢,

設計模式學習】抽象工廠模式

cpp學習抽象工廠模式; 在學習抽象工廠模式之前,先來回憶一下上一節學習的工廠方法模式; 工廠方法模式,採用多型分離的方法,將簡單工廠模式的工廠類解放為多個具體的子工廠, 從而繼承簡單工廠模式的優點,解決簡單工廠模式的缺點; 工廠方法模式的缺點:在增加

java設計模式學習筆記--簡單工廠模式

1. 什麼是簡單工廠模式 簡單工廠模式是屬於建立型模式,又叫做靜態工廠方法(Static Factory Method)模式。簡單工廠模式是由一個工廠物件決定創建出哪一種產品類的例項。但是嚴格來說,簡單工廠模式不是設計模式,它更像是一種程式設計習慣。 2.

C#設計模式之3——抽象工廠模式

宣告:本文章參考引用《C#設計模式》(科學出版社)一書。 抽象工廠(Abstract Factory)模式,是比工廠模式更高一層的抽象。在希望返回物件的幾個相關類中的一個時,可以使用該模式,每個類都能夠根據需要返回幾個不同的物件。換句話說,抽象工廠是一個工廠物件,其

《Head First 設計模式》之抽象工廠模式

《head first》書上舉的例子講的還是Pizza的例子,只不過這次是用的原料來模擬抽象共工廠模式,類太多,感覺還是大話的這個例子更貼近一點,類相對來說也少,更加清晰。大話上的例子說的是利用抽象工廠模式模擬實現不同資料庫的資料訪問。 抽象工廠模式提供了一個介面,用於建立

設計模式讀書筆記-----職責鏈模式

       去年參加校招要到長沙來,這個對於我來說不是特別喜歡(但又必須的來,誰叫咱不是985、211的娃呢),但是對於某些人來說就是福音了。大四還有課,而且學校抓的比較嚴,所以對於那些想翹課的人來

設計模式原則9----抽象工廠模式

個人部落格:開啟連結 抽象工廠模式的定義 Provide an Interface for creating families of related or dependent objects without specifying their concre

設計模式學習筆記--簡單工廠模式(Simple Factory Pattern)【建立型模式

簡單工廠模式: 工廠是用來生成產品的,簡單工廠,說明工廠能力有限因此只生成一個系列的產品。 此係列產品提供一個產品抽象,具體的產品在派生產品中進行實現。 簡單工廠(一個類),用來管理這個系列產品的生產。工廠中會有一個creat(char* name)成員函式name是需要生

設計模式讀書筆記-----建造者模式

       流水作業大家應該都清楚吧!在流水作業中,我們可以將一些複雜的東西給構建出來,例如汽車。我們都知道汽車內部構件比較複雜,由很多部件組成,例如車輪、車門、發動機、方向盤等等,對於我們使用者來

重學 Java 設計模式:實戰抽象工廠模式

![](https://img-blog.csdnimg.cn/20200524122219660.jpg) 作者:小傅哥 部落格:[https://bugstack.cn](https://bugstack.cn) > 沉澱、分享、成長,讓自己和他人都能有所收穫!

《JAVA與模式》之抽象工廠模式(轉)

場景問題   舉個生活中常見的例子——組裝電腦,我們在組裝電腦的時候,通常需要選擇一系列的配件,比如CPU、硬碟、記憶體、主機板、電源、機箱等。為討論使用簡單點,只考慮選擇CPU和主機板的問題。   事實上,在選擇CPU的時候,面臨一系列的問題,比如品牌、型號、針腳數目、