您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“Java設計模式之工廠方法和抽象工廠怎么用”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Java設計模式之工廠方法和抽象工廠怎么用”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
如果有一個客戶老王,需要購買產品,產品分別是A、B、C。
如果用傳統方法實現,分別定義A、B、C三個類,再分別創建他們所屬的方法。
在客戶對象中再分別調用他們的方法。
Product ClientProduct(String orderType) { Product product; if (orderType.equals("A")) { product = new ProductA(); } else if (orderType.equals("B")) { product = new ProductB(); } else if (orderType.equals("B")) { product = new ProductC(); } // product制作過程 product.common(); return product; }
如果我們需要再增加一個產品D,就需要判斷再增加一個分支,然后在分支里面創建產品對象,調用產品D的方法。
這樣代碼的維護性是極差的,查看我們的軟件設計七大原則,很明顯,這違反了開閉原則、依賴倒置原則.
如果又有個客戶小王,那么小王也必須依賴每個產品類,這樣就顯得冗雜。
簡單工廠(靜態工廠)模式就應用而生了。
如果我們將產品A、B、C抽象出來一個父類,再專門創建一個工廠類,在客戶購買產品時,只需要傳入產品的類型,由工廠去創建產品。
簡單工廠模式中包含如下角色:
Factory:工廠角色
工廠角色負責實現創建所有實例的內部邏輯。
Product:抽象產品角色
抽象產品角色是所創建的所有對象的父類,負責描述所有實例所共有的公共接口。
ConcreteProduct:具體產品角色
具體產品角色是創建目標,所有創建的對象都充當這個角色的某個具體類的實例。
看看我們對原始實現方式后的代碼。
產品抽象父類:
/** * @author tcy * @Date 28-07-2022 */ public class Product { public void common(){ System.out.println("這是產品父類公共方法..."); } }
產品A:
/** * @author tcy * @Date 28-07-2022 */ public class ProductA extends Product{ public void common(){ System.out.println("這是產品A方法..."); } }
產品B:
/** * @author tcy * @Date 28-07-2022 */ public class ProductB extends Product{ public void common(){ System.out.println("這是產品B方法..."); } }
工廠類:
/** * @author tcy * @Date 28-07-2022 */ public class SimpleFactory { public Product createProduct(String orderType) { Product product = null; if (orderType.equals("A")) { product = new ProductA(); } else if (orderType.equals("B")) { product = new ProductB(); } else if (orderType.equals("C")) { product = new ProductC(); } return product; } }
客戶老王類:
/** * @author tcy * @Date 28-07-2022 */ public class Client { SimpleFactory simpleFactory; public Client(SimpleFactory simpleFactory) { this.simpleFactory = simpleFactory; } public Product orderProduct(String orderType) { Product product; product = simpleFactory.createProduct(orderType); //調用每個產出相應的方法 product.common(); System.out.println(product.getClass()); return product; } public static void main(String[] args) { Client client=new Client(new SimpleFactory()); client.orderProduct("A"); } }
這樣簡單工廠模式就實現了,這樣的話老王和具體的產品就很好的解耦了,也不需要老王再依賴具體產品類,依賴倒置問題就很好的解決了。
如果增加一個產品D,需要再重新定義一個D類,實現product接口,而后在工廠類中增加一個分支結構。
顯而易見這樣實現,缺陷依然存在:
1、工廠類集中了所有產品創建邏輯,職責過重,一旦發生異常,整個系統將受影響。
2、使用簡單工廠模式將會增加系統中類的個數,在一定程序上增加了系統的復雜度和理解難度。
3、系統擴展困難,一旦增加新產品不得不修改工廠邏輯,在產品類型較多時,可能造成邏輯過于復雜。
4、簡單工廠模式由于使用了靜態工廠方法,造成工廠角色無法形成基于繼承的等級結構。
這種方法只是一種編碼方式,并不輸入設計模式的一種,且局限于產品種類較少。
在簡單工廠中老王需要具體的產品,就在他自己的類中去創建需要的產品,老王雖然不依賴具體產品,但老王現在需要依賴工廠實現類了。
簡單工廠是將產品類抽象化,具體的產品由工廠類去實現。
如果我們將工廠類也抽象化,那就引出了我們今天第一個設計模式——工廠方法。
工廠方法有四個角色:
1、抽象工廠(Abstract Factory):提供了創建產品的接口,調用者通過它訪問具體工廠的工廠方法 createProduct() 來創建產品。
2、具體工廠(ConcreteFactory):主要是實現抽象工廠中的抽象方法,完成具體產品的創建。
3、抽象產品(Product):定義了產品的規范,描述了產品的主要特性和功能。
4、具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來創建,它同具體工廠之間一一對應。
我們對簡單工廠代碼進行改造。
抽象產品父類、產品A類、產品B類保持不變。重點看工廠類
抽象工廠類:
/** * @author tcy * @Date 28-07-2022 */ public abstract class AbstractFactory { public abstract Product createProduct(String orderType); }
具體實現工廠A類:
/** * @author tcy * @Date 28-07-2022 */ public class ConcreteFactoryA extends AbstractFactory{ @Override public Product createProduct(String orderType) { System.out.println("參數為:"+orderType); return new ProductA(); } }
具體實現工廠B類:
/** * @author tcy * @Date 28-07-2022 */ public class ConcreteFactoryB extends AbstractFactory{ @Override public Product createProduct(String orderType) { return new ProductB(); } }
老王類:
/** * @author tcy * @Date 28-07-2022 */ public class Client { AbstractFactory simpleFactory; public Client(AbstractFactory simpleFactory) { this.simpleFactory = simpleFactory; } public Product orderProduct(String orderType) { Product product; product = simpleFactory.createProduct(orderType); //調用每個產出相應的方法 product.common(); System.out.println(product.getClass()); return product; } public static void main(String[] args) { Client client=new Client(new ConcreteFactoryA()); client.orderProduct("A"); } }
這樣的好處就在于老王只管他要關注的抽象工廠,具體是哪個工廠實現類生產產品,老王也不需要關注。
典型的解耦框架。高層模塊只需要知道產品的抽象類,無須關心其他實現類,滿足迪米特法則、依賴倒置原則和里氏替換原則。
缺點也是顯而易見的:
類的個數容易過多,增加復雜度。
考慮到系統的可擴展性,需要引入抽象層,在客戶端代碼中均使用抽象層進行定義,增加了系統的抽象性和理解難度。
抽象產品只能生產一種產品。
如果對工廠方法依然一知半解的話,接著往下看工廠方法的一個典型實現
在JDK中對工廠方法有大量的運用,其中比較典型的是
new ArrayList<>().iterator();
我們知道集合的一個大分支依賴的是Collection接口,我們以ArrayList作為舉例。
Collection接口相當于產品的抽象父類,ArrayList相當于具體產品。
Iterator是一個抽象工廠,在ArrayList中有一個Itr內部類實現了Iterator接口
當我們調用集合的iterator()方法遍歷對象時,就會調用各自類的具體實現方法。
有一天,產品A、B、C升級改造了,三種產品分別有紅色和藍色,如果還用工廠方法的話,那簡直是個災難,具體工廠實現類需要六個。
就引出我們今天的第二個設計模式——抽象工廠。
抽象工廠模式(Abstract Factory Pattern):提供一個接口,用于創建創建一系列相關或相互依賴對象的家族,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式,屬于對象創建型模式。
抽象工廠模式與工廠方法模式區別在于,工廠方法模式針對的是一個產品等級結構。
而抽象工廠模式則需要面對多個產品等級結構(各種顏色),一個工廠等級結構可以負責多個不同產品等級結構(不同顏色)中的產品對象的創建 。
抽象工廠依然是四個角色:
AbstractFactory:抽象工廠
ConcreteFactory:具體工廠
AbstractProduct:抽象產品
Product:具體產品
我們開始改造工廠方法代碼,既然是要把產品都分成一組,那理應把產品A、B、C都抽象出來,再讓工廠類去實現各個產品的不同顏色,也就是概念中的——用于創建創建一系列相關或相互依賴對象的家族。
接口看改造后的代碼:
產品抽象類:
/** * @author tcy * @Date 28-07-2022 */ public interface Product { public void common(); }
產品抽象A家族類:
/** * @author tcy * @Date 28-07-2022 */ public abstract class ProductA implements Product { public abstract void common(); }
產品抽象B家族類:
/** * @author tcy * @Date 28-07-2022 */ public abstract class ProductB implements Product { public abstract void common(); }
具體紅色產品A類:
/** * @author tcy * @Date 28-07-2022 */ public class RedProductA extends ProductA{ @Override public void common() { System.out.println("這是紅色的產品A"); } }
具體藍色產品A類:
/** * @author tcy * @Date 28-07-2022 */ public class BlueProductA extends ProductA { @Override public void common() { System.out.println("這是藍色的產品A"); } }
抽象A家族工廠類:
/** * @author tcy * @Date 28-07-2022 */ public interface AbstractProductFactory { public ProductA createProduct(String orderType); }
實現A家族工廠類:
/** * @author tcy * @Date 28-07-2022 */ public class ConcreateProductAFactory implements AbstractProductFactory{ @Override public ProductA createProduct(String orderType) { return new BlueProductA(); } }
老王類:
/** * @author tcy * @Date 28-07-2022 */ public class Client { ConcreateProductAFactory simpleFactory; public Client(ConcreateProductAFactory simpleFactory) { this.simpleFactory = simpleFactory; } public ProductA orderProduct(String orderType) { ProductA product; product = simpleFactory.createProduct(orderType); //調用每個產出相應的方法 product.common(); System.out.println(product.getClass()); return product; } public static void main(String[] args) { Client client=new Client(new ConcreateProductAFactory()); client.orderProduct("A"); } }
這樣的話,每天工廠類可以把A的產品家族類(紅、藍)都實現,抽象工廠模式隔離了具體類的生成,使得老王并不需要知道什么產品被創建,從具體的產品解耦出來。
當一個產品族中的多個對象被設計成一起工作時,它能夠保證客戶端始終只使用同一個產品族中的對象。
如果要增加新產品、和新工廠很容易,如果再增加一個等級(顏色)代碼修改起來就很痛苦了。
抽象工廠模式在Spring中有大量的運用。
比較典型的是,BeanFactory 是用于管理 Bean 的一個工廠,所有工廠都是 BeanFactory 的子類。這樣我們可以通過 IOC 容器來管理訪問 Bean,根據不同的策略調用 getBean() 方法,從而獲得具體對象。
BeanFactory 的子類主要有
ClassPathXmlApplicationContext、
XmlWebApplicationContext、
StaticWebApplicationContext、
StaticApplicationContext。
在 Spring 中,DefaultListableBeanFactory 實現了所有工廠的公共邏輯。
讀到這里,這篇“Java設計模式之工廠方法和抽象工廠怎么用”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。