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

来源:http://www.cnblogs.com/jenkinschan/archive/2016/07/31/5712874.html
-Advertisement-
Play Games

一、概述 抽象工廠模式提供一個介面,用於創建相關或依賴對象的家族,而不需要明確指定具體類。可以理解成是多個工廠方法的組合。 二、解決問題 在工廠方法模式中,我們的具體創建者每次使用都只能創建一個同類型的對象,假如我們現在需要的是多個不同類型的對象,工廠方法就滿足不了需求了。這時我們可以把多個工廠方法 ...


一、概述

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

二、解決問題

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

三、結構類圖

四、成員角色

  抽象工廠(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、當系列產品不固定,在以後可能會增加整個系列產品時使用。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目鏈接:http://acm.nyist.net/JudgeOnline/problem.php?pid=860 My思路: 先用兩個字元串儲存這兩個實數,然後再用另外兩個字元串儲存去掉符號和前後多餘的0後的新"實數",最後只需要比較兩個化簡後的新字元就ok了。 My代碼實現: 1 #includ ...
  • 用php進行靜態類型編程,估計是我的一個心結。 依次有幾篇文章都記錄了我的一些探索: 通過指定函數/方法形參類型提高PHP代碼可靠性 http://www.cnblogs.com/x3d/p/4285787.html 用Yii框架中的collections體驗PHP類型化編程 http://www. ...
  • 一、Get/Load Get方法是立即檢索,而load是延遲檢索,他們都是根據主鍵進行查詢。在<class>標簽中,若把lazy屬性改為false,load方法就會立即檢索,class中的lazy屬性僅對load方法有效。在使用load時,當資料庫沒有找到數據時,會有ObjectNotFoundEx ...
  • 理想的情況下,一個 Java 程式使用 JVM 的預設設置也可以運行得很好,所以一般來說,沒有必要設置任何 JVM 參數。然而,由於一些性能問題(很不幸的是,這些問題經常出現),一些相關的 JVM 參數知識會是我們工作中得好伙伴。在這篇文章中,我們將介紹一些關於 JVM 記憶體管理的參數。知道並理解這 ...
  • 問題描述: 輸入一組整數,求出這組數字子序列和中最大值。也就是只要求出最大子序列的和,不必求出最大的那個序列。例如: 序列:-2 11 -4 13 -5 -2,則最大子序列和為20。 序列:-6 2 4 -7 5 3 2 -1 6 -9 10 -2,則最大子序列和為16。 O(n)解法: ...
  • Zend\Mvc\MvcEvent繼承自Zend\EventManager\Event,在Zend\Mvc\Application::bootstrap()執行時觸發。如果你的控制器實現了Zend\Mvc\InjectApplicationEventInterface,MvcEvent將會被註入到這 ...
  • Schema約束 俗話說得好 好記性不如爛筆頭。 看了下WebService視頻,覺得還是得下筆記。 觀看的視頻地址:http://edu.51cto.com/lesson/id-25757.html 複習下xml約束 bool.xsd是book.xml的約束文檔 schema規範中: 1. 所有標 ...
  • 1.意圖 定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。 2.別名 依賴(Depenents),發佈-訂閱(Publish-subscribe) 3.動機 一個目標可以有任意數目的依賴它的觀察者。一旦目標的狀態發生改變,所有的觀察者都得到通知 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...