【設計模式】學習筆記6:抽象原廠模式(Abstract Factory)

來源:互聯網
上載者:User

本文出自   http://blog.csdn.net/shuangde800


——所有工廠都是用來封裝對象的建立

——工廠是很有威力的技巧,協助我們針對抽象編程,而不要針對具體類編程。


認識抽象原廠模式

在之前的原廠模式已經建立了一個比薩工廠,但是真正要生產的產品——比薩,卻還沒有涉及到。

比薩店會生產很多不同的比薩產品,而比薩又有格式不同風格的原料。

所以,我們要建造一個工廠來生產原料,這個工廠將負責建立原料家族中的每一個原料:醬料、芝士、麵糰等。


開始先為工廠定義一個介面,這個介面負責建立所有的原料:

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


下面要做的是:

1、給每個比薩店建造一個工廠。需要建立實現PizzaIngredientFactory介面的類,實現介面的方法。

2、實現一組原料類供工廠使用。

3、把這一切組織起來,將新的原料工廠整合進舊的PizzaStore中。


下面建立了紐約原料工廠,實現了PizzaIngredientFactory介面:

public class NYPizzaIngredientFactory implements PizzaIngredientFactory { public Dough createDough() {return new ThinCrustDough();} public Sauce createSauce() {return new MarinaraSauce();} public Cheese createCheese() {return new ReggianoCheese();} public Veggies[] createVeggies() {Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };return veggies;} public Pepperoni createPepperoni() {return new SlicedPepperoni();}public Clams createClam() {return new FreshClams();}}

然後就可以重新定義“比薩”,這個抽象類別:

public abstract class Pizza {String name;Dough dough;Sauce sauce;Veggies veggies[];Cheese cheese;Pepperoni pepperoni;Clams clam;abstract void prepare();//把prepare申明為抽象,在這個方法中,需要手機比薩所需的原料,而這些原料當然是來自原料工廠了void bake() {System.out.println("Bake for 25 minutes at 350");}void cut() {System.out.println("Cutting the pizza into diagonal slices");}void box() {System.out.println("Place pizza in official PizzaStore box");}void setName(String name) {this.name = name;}String getName() {return name;}public String toString() {StringBuffer result = new StringBuffer();result.append("---- " + name + " ----\n");if (dough != null) {result.append(dough);result.append("\n");}if (sauce != null) {result.append(sauce);result.append("\n");}if (cheese != null) {result.append(cheese);result.append("\n");}if (veggies != null) {for (int i = 0; i < veggies.length; i++) {result.append(veggies[i]);if (i < veggies.length-1) {result.append(", ");}}result.append("\n");}if (clam != null) {result.append(clam);result.append("\n");}if (pepperoni != null) {result.append(pepperoni);result.append("\n");}return result.toString();}}

然後就是建立真正的比薩了! 比薩店生產的比薩都是繼承自Pizza類,假設要生產一個乳酪比薩(CheesePizza):

// 這是應用了簡單原廠模式// 比薩要用到原料,把生產原料任務委託給了ingredientFactory工廠public class CheesePizza extends Pizza {PizzaIngredientFactory ingredientFactory; public CheesePizza(PizzaIngredientFactory ingredientFactory) {this.ingredientFactory = ingredientFactory;}        // 實現prepare方法void prepare() {System.out.println("Preparing " + name);dough = ingredientFactory.createDough();sauce = ingredientFactory.createSauce();cheese = ingredientFactory.createCheese();}}

上面這個真正的比薩,是不是很眼熟?沒錯,起始就是簡單原廠模式, Pizza利用相關的工廠生產原料。所生產的原料依賴所使用的工廠,Pizza類根本不關心這些原料,它只知道如何製作比薩。現在,Pizza和原料之間被解耦,無論原料工廠是在北京還是上海,Pizza類都可以輕易地複用。

最後,是時候讓新的比薩店登場了! 

public class NYPizzaStore extends PizzaStore { protected Pizza createPizza(String item) {Pizza pizza = null;// 原料工廠負責生產所有的原料PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory(); if (item.equals("cheese")) {pizza = new CheesePizza(ingredientFactory); // 把工廠傳遞給每一個比薩,以便使比薩能從工廠中取得原料pizza.setName("New York Style Cheese Pizza");  } else if (item.equals("veggie")) { pizza = new VeggiePizza(ingredientFactory);pizza.setName("New York Style Veggie Pizza"); } else if (item.equals("clam")) { pizza = new ClamPizza(ingredientFactory);pizza.setName("New York Style Clam Pizza"); } else if (item.equals("pepperoni")) {pizza = new PepperoniPizza(ingredientFactory);pizza.setName("New York Style Pepperoni Pizza"); } return pizza;}

小結:

上面一連串代碼到底做了什嗎?

其實就做了一件事,引入了新類型的工廠——抽象工廠,來建立比薩原料家族。

我們建立了介面類PizzaIngredientFactory,這個介面可以建立產品的家族,利用這個介面,我們的代碼將從實際工廠解耦,以便在不同上下文中實現各式各樣的工廠,製作出不同的產品。

定義抽象原廠模式

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


抽象工廠允許客戶使用抽象的介面來建立一組相關的產品,而不需要知道(或關心)實際產出的具體產品是什麼。這樣一來,客戶就從具體的產品中解藕。

生產原料的類圖:


我們可以發現抽象工廠主要是為“產品”而服務的。

抽象工廠的方法經常以Factory 方法的方式實現(例如createDough(), createSource(),每個方法都被聲明為抽象,而子類的方法覆蓋這些方法來建立某些對象),抽象工廠的任務是定義一個負責建立一組產品的介面。這個介面內的每個方法都負責建立一個具體產品,同時我們利用實現抽象工廠的子類來提供這些具體的做法,所以,在抽象工廠中利用Factory 方法實現生產的做法是相當自然的做法。



比較Factory 方法和抽象工廠


      抽象工廠和Factory 方法都是負責建立對象,但Factory 方法用的是繼承,而抽象方法用的是對象的組合

      利用Factory 方法建立對象,需要拓展一個類,並覆蓋它的Factory 方法。整個Factory 方法模式,只不過就是通過子類來建立對象。用這種做法,客戶只需要知道他們所使用的抽象類別型就可以了,而由子類負責決定具體的類型,將客戶從具體類型中解耦。

      而抽象工廠用來建立一個產品家族的抽象類別型,這個類型的子類定義了產品被產生的方法。要想使用這個工廠,必須先執行個體化它,然後將它傳入一些針對抽象類別型所寫的代碼中。所以和Factory 方法一樣,也實現解耦。

      總之,他們都能將對象的建立封裝起來,使應用程式解耦,並降低對特定實現的依賴。




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.