Java工廠模式之簡單工廠,工廠方法,抽象工廠模式詳解
1、簡單工廠模式
1.定義
簡單工廠模式(Simple Factory Pattern)是指由一個工廠對象決定創建出哪一種產品類的實例。
屬於創建型模式,但它不屬於GOF23種設計模式。
2.代碼案例
假設以罐頭產品的制造為案例
第一步:定義罐頭的頂層接口類ICanned
/** * @Package: com.hzg.study.design.pattern.factory.simplefactory * @Description: 罐頭頂層接口 * @Author: HuangZhiGao * @CreateDate: 2022-02-17 17:52 */ public interface ICanned { /** * 展示罐頭名稱 * <p/> * * @return void * @author HuangZhiGao * @date 2022/2/17/017 17:54 */ void showCannedName(); }
第二步:分別編寫兩個具體的實現類FruitCanned和BeefCanned
/** * @Package: com.hzg.study.design.pattern.factory.simplefactory * @Description: 水果罐頭 * @Author: HuangZhiGao * @CreateDate: 2022-02-17 17:56 */ public class FruitCanned implements ICanned { @Override public void showCannedName() { System.out.println("名稱:水果罐頭"); } }
/** * @Package: com.hzg.study.design.pattern.factory.simplefactory * @Description: 牛肉罐頭 * @Author: HuangZhiGao * @CreateDate: 2022-02-17 17:57 */ public class BeefCanned implements ICanned { @Override public void showCannedName() { System.out.println("名稱:牛肉罐頭"); } }
第三步:編寫工廠類
import com.hzg.study.design.pattern.factory.common.ICanned; /** * @Package: com.hzg.study.design.pattern.factory.simplefactory * @Description: 罐頭工廠類 * @Author: HuangZhiGao * @CreateDate: 2022-02-17 18:16 */ public class CannedFactory { /** * 創建罐頭的方法 * <p/> * * @param clazz * @return com.hzg.study.design.pattern.factory.common.ICanned * @author HuangZhiGao * @date 2022/2/17/017 18:18 */ public ICanned createCanned(Class<? extends ICanned> clazz) { if (null != clazz) { try { return clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } } return null; } }
第四步:main方法測試、查看類圖
import com.hzg.study.design.pattern.factory.common.BeefCanned; import com.hzg.study.design.pattern.factory.common.FruitCanned; import com.hzg.study.design.pattern.factory.common.ICanned; /** * @Package: com.hzg.study.design.pattern.factory.simplefactory * @Description: 測試類 * @Author: HuangZhiGao * @CreateDate: 2022-02-17 18:22 */ public class SimpleFactoryTest { public static void main(String[] args) { CannedFactory cannedFactory = new CannedFactory(); ICanned fruitCanned = cannedFactory.createCanned(FruitCanned.class); fruitCanned.showCannedName(); System.out.println("----------------------------------------"); ICanned beefCanned = cannedFactory.createCanned(BeefCanned.class); beefCanned.showCannedName(); } }
運行結果:
名稱:水果罐頭
—————————————-
名稱:牛肉罐頭
簡單工廠模式類圖:
3.適用場景
工廠類負責創建的對象較少,不需要關心創建對象的邏輯
4.優缺點
優點:
簡化瞭客戶端創建對象的過程
缺點:
1.工廠類職責相對較重,在一定程度上可能違背開閉原則(增加新的產品可能需要修改工廠類邏輯)
2.不易於擴展過於復雜的產品結構
2、工廠方法模式
1.定義
工廠方法模式(Factory Method Pattern)是指定義一個創建對象的接口,但讓實現這個接口的類來決定實例化哪個類,工廠方法讓類的實例化推遲到子類中進行。
屬於創建型設計模式。
2.代碼案例
需要使用到簡單工廠模式的ICanned、FruitCanned、BeefCanned
第一步:定義罐頭工廠頂層接口類ICannedFactory
import com.hzg.study.design.pattern.factory.common.ICanned; /** * @Package: com.hzg.study.design.pattern.factory.factorymethod * @Description: 罐頭工廠頂層接口 * @Author: HuangZhiGao * @CreateDate: 2022-02-18 10:03 */ public interface ICannedFactory { /** * 創建罐頭方法 * <p/> * * @return void * @author HuangZhiGao * @date 2022/2/18/018 10:04 */ ICanned doCreateCanned(); }
第二步:分別編寫兩個具體的工廠實現類FruitCannedFactory和BeefCannedFactory
import com.hzg.study.design.pattern.factory.common.FruitCanned; import com.hzg.study.design.pattern.factory.common.ICanned; /** * @Package: com.hzg.study.design.pattern.factory.factorymethod * @Description: 水果罐頭工廠類 * @Author: HuangZhiGao * @CreateDate: 2022-02-18 10:05 */ public class FruitCannedFactory implements ICannedFactory { @Override public ICanned doCreateCanned() { return new FruitCanned(); } }
import com.hzg.study.design.pattern.factory.common.BeefCanned; import com.hzg.study.design.pattern.factory.common.ICanned; /** * @Package: com.hzg.study.design.pattern.factory.factorymethod * @Description: 牛肉罐頭工廠類 * @Author: HuangZhiGao * @CreateDate: 2022-02-18 10:08 */ public class BeefCannedFactory implements ICannedFactory { @Override public ICanned doCreateCanned() { return new BeefCanned(); } }
第三步:main方法測試、查看類圖
import com.hzg.study.design.pattern.factory.common.BeefCanned; import com.hzg.study.design.pattern.factory.common.FruitCanned; import com.hzg.study.design.pattern.factory.common.ICanned; /** * @Package: com.hzg.study.design.pattern.factory.simplefactory * @Description: 測試類 * @Author: HuangZhiGao * @CreateDate: 2022-02-17 18:22 */ public class SimpleFactoryTest { public static void main(String[] args) { CannedFactory cannedFactory = new CannedFactory(); ICanned fruitCanned = cannedFactory.createCanned(FruitCanned.class); fruitCanned.showCannedName(); System.out.println("----------------------------------------"); ICanned beefCanned = cannedFactory.createCanned(BeefCanned.class); beefCanned.showCannedName(); } }
運行結果:
名稱:水果罐頭
—————————————-
名稱:牛肉罐頭
工廠方法模式類圖:
3.適用場景
創建對象需要大量重復的代碼。
客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節。
一個類通過其子類來指定創建哪個對象。
4.優缺點
優點:
1.用戶隻需關心所需產品對應的工廠,無須關心創建細節。
2.加入新產品符合開閉原則,提高瞭系統的可擴展性。
缺點:
1.類的個數容易過多,增加瞭代碼結構的復雜度。
2.增加瞭系統的抽象性和理解難度。
3、抽象工廠模式
1.定義
抽象工廠模式(Abstract Factory Pattern)是指提供一個創建一系列相關或相互依賴對象的接口,無須指定他們具體的類。
屬於創建型設計模式。
抽象工廠模式有產品族和產品等級的概念,可以通俗的理解為
產品族相當於不同品牌的產品合集,產品等級相當於不同品牌的同一種產品
例如:水果罐頭的材料信息、標簽信息組成瞭一個產品族,牛肉罐頭的材料信息、標簽信息組成瞭一個產品族
水果罐頭的材料信息、牛肉罐頭的材料信息組成一個產品等級,水果罐頭的標簽信息、牛肉罐頭的標簽信息組成一個產品等級
2.代碼案例
假設制造一個罐頭包含兩個部分(材料信息+標簽信息)
第一步:分別定義罐頭材料信息接口IMaterialInfo和罐頭標簽信息接口ITagInfo
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: 罐頭材料信息接口 * @Author: HuangZhiGao * @CreateDate: 2022-02-18 10:51 */ public interface IMaterialInfo { /** * 打印材料信息 * <p/> * * @return void * @author HuangZhiGao * @date 2022/2/18/018 10:57 */ void printMaterialInfo(); }
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: 罐頭標簽信息接口 * @Author: HuangZhiGao * @CreateDate: 2022-02-18 10:48 */ public interface ITagInfo { /** * 打印標簽信息 * <p/> * * @return void * @author HuangZhiGao * @date 2022/2/18/018 10:57 */ void printTagInfo(); }
第二步:定義罐頭的頂層工廠接口類ICannedFactory
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: 頂層工廠接口:一個罐頭包含兩個部分(材料信息+標簽信息) * @Author: HuangZhiGao * @CreateDate: 2022-02-18 10:47 */ public interface ICannedFactory { IMaterialInfo createMaterialInfo(); ITagInfo createTagInfo(); }
第三步:分別編寫具體實現類FruitMaterialInfo、FruitTagInfo和BeefMaterialInfo、BeefTagInfo
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: * @Author: HuangZhiGao * @CreateDate: 2022-02-18 11:05 */ public class FruitMaterialInfo implements IMaterialInfo { @Override public void printMaterialInfo() { System.out.println("材料:水果"); } }
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: * @Author: HuangZhiGao * @CreateDate: 2022-02-18 11:05 */ public class FruitTagInfo implements ITagInfo { @Override public void printTagInfo() { System.out.println("標簽:2022升級版水果罐頭"); } }
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: * @Author: HuangZhiGao * @CreateDate: 2022-02-18 11:05 */ public class BeefMaterialInfo implements IMaterialInfo { @Override public void printMaterialInfo() { System.out.println("材料:牛肉"); } }
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: * @Author: HuangZhiGao * @CreateDate: 2022-02-18 11:06 */public class BeefTagInfo implements ITagInfo { @Override public void printTagInfo() { System.out.println("標簽:2022升級版牛肉罐頭"); }}/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: * @Author: HuangZhiGao * @CreateDate: 2022-02-18 11:06 */ public class BeefTagInfo implements ITagInfo { @Override public void printTagInfo() { System.out.println("標簽:2022升級版牛肉罐頭"); } }
第四步:分別編寫工廠具體實現類FruitCannedFactory、BeefCannedFactory
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: * @Author: HuangZhiGao * @CreateDate: 2022-02-18 11:04 */ public class FruitCannedFactory implements ICannedFactory { @Override public IMaterialInfo createMaterialInfo() { return new FruitMaterialInfo(); } @Override public ITagInfo createTagInfo() { return new FruitTagInfo(); } }
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: * @Author: HuangZhiGao * @CreateDate: 2022-02-18 11:04 */ public class BeefCannedFactory implements ICannedFactory { @Override public IMaterialInfo createMaterialInfo() { return new BeefMaterialInfo(); } @Override public ITagInfo createTagInfo() { return new BeefTagInfo(); } }
第五步:main方法測試、查看類圖
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: * @Author: HuangZhiGao * @CreateDate: 2022-02-18 11:12 */ public class AbstractFactoryTest { public static void main(String[] args) { ICannedFactory beefCannedFactory = new BeefCannedFactory(); beefCannedFactory.createMaterialInfo().printMaterialInfo(); beefCannedFactory.createTagInfo().printTagInfo(); System.out.println("----------------------------------------"); ICannedFactory fruitCannedFactory = new FruitCannedFactory(); fruitCannedFactory.createMaterialInfo().printMaterialInfo(); fruitCannedFactory.createTagInfo().printTagInfo(); } }
運行結果:
材料:牛肉
標簽:2022升級版牛肉罐頭
—————————————-
材料:水果
標簽:2022升級版水果罐頭
抽象工廠模式類圖:
3.適用場景
客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節。
強調一系列相關的產品對象(屬於同一產品族)一起使用創建對象需要大量重復的代碼。
提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現。
4.優缺點
優點:
1.具體產品在應用層代碼隔離,無須關心創建細節。
2.將一個系列的產品族統一到一起創建。
缺點:
1.規定瞭所有可能被創建的產品集合,產品族中擴展新的產品困難,需要修改抽象工廠的接口。
2.增加瞭系統的抽象性和理解難度。
4、總結
簡單工廠、工廠方法和抽象工廠的區別:
工廠方法和抽象工廠是GOF23種設計模式中的兩種,簡單工廠不是一種設計模式,可以理解為是一種約定俗成的編碼習慣。
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!