Java?深入理解創(chuàng)建型設(shè)計(jì)模式之抽象工廠模式
1.什么是抽象工廠模式?
- 抽象工廠模式: 定義了一個(gè)interface用于創(chuàng)建相關(guān)或有依賴關(guān)系的對(duì)象簇,而無(wú)需指明具體的類。
- 抽象工廠模式可以將簡(jiǎn)單工廠模式和工廠方法模式進(jìn)行整合。
- 從設(shè)計(jì)層面看,抽象工廠模式就是對(duì)簡(jiǎn)單工廠模式的改進(jìn)(或者稱為進(jìn)一步的抽象)。
- 將工廠抽象成兩層,AbsFactory(抽象工廠))和具體實(shí)現(xiàn)的工廠子類。程序員可以根據(jù)創(chuàng)建對(duì)象類型使用對(duì)應(yīng)的工廠子類。這樣將單個(gè)的簡(jiǎn)單工廠類變成了工廠簇,更利于代碼的維護(hù)和擴(kuò)展。
我們?nèi)匀灰陨弦黄恼碌陌咐秊橹鳎嫵龀橄蠊S模式下的類圖。
2.案例代碼
首先仍然是Pizza種類相關(guān)的幾個(gè)類。
package com.szh.factory.abstractfactory.pizza; /** * 聲明Pizza類為抽象類 */ public abstract class Pizza { //Pizza名稱 protected String name; //準(zhǔn)備原材料,不同的披薩不一樣。因此,我們做成抽象方法,具體的原材料實(shí)現(xiàn)交給它的子類去完成 public abstract void prepare(); //烘烤 public void bake() { System.out.println(name + " baking;"); } //切割 public void cut() { System.out.println(name + " cutting;"); } //打包 public void box() { System.out.println(name + " boxing;"); } public void setName(String name) { this.name = name; } }
package com.szh.factory.abstractfactory.pizza; public class LDPepperPizza extends Pizza { @Override public void prepare() { setName("倫敦的胡椒pizza"); System.out.println("倫敦的胡椒pizza 準(zhǔn)備原材料"); } }
package com.szh.factory.abstractfactory.pizza; public class LDCheesePizza extends Pizza { @Override public void prepare() { setName("倫敦的奶酪pizza"); System.out.println("倫敦的奶酪pizza 準(zhǔn)備原材料"); } }
package com.szh.factory.abstractfactory.pizza; public class BJPepperPizza extends Pizza { @Override public void prepare() { setName("北京的胡椒pizza"); System.out.println("北京的胡椒pizza 準(zhǔn)備原材料"); } }
package com.szh.factory.abstractfactory.pizza; public class BJCheesePizza extends Pizza { @Override public void prepare() { setName("北京的奶酪pizza"); System.out.println("北京的奶酪pizza 準(zhǔn)備原材料"); } }
下面是抽象工廠和工廠方法的區(qū)別之處。
package com.szh.factory.abstractfactory.order; import com.szh.factory.abstractfactory.pizza.Pizza; //一個(gè)抽象工廠模式的抽象層(接口) public interface AbsFactory { //讓下面的工廠子類來(lái)具體實(shí)現(xiàn) public Pizza createPizza(String orderType); }
package com.szh.abstractfactory.order; import com.szh.abstractfactory.pizza.BJCheesePizza; import com.szh.abstractfactory.pizza.BJPepperPizza; import com.szh.abstractfactory.pizza.Pizza; public class BJFactory implements AbsFactory { @Override public Pizza createPizza(String orderType) { Pizza pizza = null; if("cheese".equals(orderType)) { pizza = new BJCheesePizza(); } else if ("pepper".equals(orderType)){ pizza = new BJPepperPizza(); } return pizza; } }
package com.szh.abstractfactory.order; import com.szh.abstractfactory.pizza.LDCheesePizza; import com.szh.abstractfactory.pizza.LDPepperPizza; import com.szh.abstractfactory.pizza.Pizza; public class LDFactory implements AbsFactory { @Override public Pizza createPizza(String orderType) { Pizza pizza = null; if ("cheese".equals(orderType)) { pizza = new LDCheesePizza(); } else if ("pepper".equals(orderType)) { pizza = new LDPepperPizza(); } return pizza; } }
package com.szh.factory.abstractfactory.order; import com.szh.factory.abstractfactory.pizza.Pizza; import java.util.Scanner; public class OrderPizza { AbsFactory absFactory; public OrderPizza(AbsFactory absFactory) { setFactory(absFactory); } private void setFactory(AbsFactory absFactory) { Pizza pizza = null; String orderType = ""; // 用戶輸入 this.absFactory = absFactory; do { orderType = getType(); // factory 可能是北京的工廠子類,也可能是倫敦的工廠子類 pizza = absFactory.createPizza(orderType); if (pizza != null) { // 訂購(gòu)ok pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } else { System.out.println("訂購(gòu)失敗"); break; } } while (true); } // 寫一個(gè)方法,可以獲取客戶希望訂購(gòu)的披薩種類 private String getType() { Scanner scanner = new Scanner(System.in); System.out.println("請(qǐng)輸入 pizza 種類: "); String str = scanner.nextLine(); return str; } }
最后是測(cè)試類。
package com.szh.abstractfactory; import com.szh.abstractfactory.order.BJFactory; import com.szh.abstractfactory.order.LDFactory; import com.szh.abstractfactory.order.OrderPizza; import java.util.Scanner; public class MainTest { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String content = scanner.next(); if ("Beijing".equals(content)) { new OrderPizza(new BJFactory()); } else if ("London".equals(content)) { new OrderPizza(new LDFactory()); } else { System.out.println("無(wú)法預(yù)先匹配Pizza種類...."); scanner.close(); } } }
3.工廠方法 + 抽象工廠總結(jié)
- 工廠模式的意義:將實(shí)例化對(duì)象的代碼提取出來(lái),放到一個(gè)類中統(tǒng)一管理和維護(hù),達(dá)到和主項(xiàng)目的依賴關(guān)系的解耦。從而提高項(xiàng)目的擴(kuò)展和維護(hù)性。
- 遵循了依賴倒轉(zhuǎn)原則:創(chuàng)建對(duì)象實(shí)例時(shí),不要直接new類,而是把這個(gè)new類的動(dòng)作放在一個(gè)工廠的方法中,并返回。有的書上說(shuō),變量不要直接持有具體類的引用。 不要讓類繼承具體類,而是繼承抽象類或者是實(shí)現(xiàn)interface(接口)不要覆蓋基類中已經(jīng)實(shí)現(xiàn)的方法。
到此這篇關(guān)于Java 深入理解創(chuàng)建型設(shè)計(jì)模式之抽象工廠模式的文章就介紹到這了,更多相關(guān)Java 抽象工廠模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中Vector與ArrayList的區(qū)別詳解
本篇文章是對(duì)Java中Vector與ArrayList的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06Java IO復(fù)用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java IO復(fù)用的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下吧2017-05-05Java協(xié)程編程之Loom項(xiàng)目實(shí)戰(zhàn)記錄
這篇文章主要介紹了Java協(xié)程編程之Loom項(xiàng)目嘗鮮,如果用嘗鮮的角度去使用Loom項(xiàng)目,可以提前窺探JVM開發(fā)者們是如何基于協(xié)程這個(gè)重大特性進(jìn)行開發(fā)的,這對(duì)于提高學(xué)習(xí)JDK內(nèi)核代碼的興趣有不少幫助,需要的朋友可以參考下2021-08-08WPF實(shí)現(xiàn)自定義一個(gè)自刪除的多功能ListBox
這篇文章主要為大家詳細(xì)介紹了如何利用WPF實(shí)現(xiàn)自定義一個(gè)自刪除的多功能ListBox,文中示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-12-12Spring Boot Maven 打包可執(zhí)行Jar文件的實(shí)現(xiàn)方法
這篇文章主要介紹了Spring Boot Maven 打包可執(zhí)行Jar文件的實(shí)現(xiàn)方法,需要的朋友可以參考下2018-02-02Dubbo?retries?超時(shí)重試機(jī)制的問(wèn)題原因分析及解決方案
這篇文章主要介紹了Dubbo?retries?超時(shí)重試機(jī)制的問(wèn)題,解決方案是通過(guò)修改dubbo服務(wù)提供方,將timeout超時(shí)設(shè)為20000ms或者設(shè)置retries=“0”,禁用超時(shí)重試機(jī)制,感興趣的朋友跟隨小編一起看看吧2022-04-04