自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

設計模式系列—抽象工廠模式

系統(tǒng)
本篇和大家一起來學習抽象工廠模式相關(guān)內(nèi)容。

 前言

  • 23種設計模式速記
  • 單例(singleton)模式
  • 工廠方法(factory method)模式

前面說完了工廠方法模式,我們發(fā)現(xiàn)工廠方法模式存在一個嚴重的問題:一個具體工廠只能創(chuàng)建一類產(chǎn)品 ,而實際過程中一個工廠往往需要生產(chǎn)多類產(chǎn)品。為了解決上述問題,可以使用抽象工廠模式,本篇和大家一起來學習抽象工廠模式相關(guān)內(nèi)容。

模式定義
抽象工廠模式,即Abstract Factory Pattern,提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無須指定它們具體的類;具體的工廠負責實現(xiàn)具體的產(chǎn)品實例。

抽象工廠模式是工廠方法模式的升級版本,工廠方法模式只生產(chǎn)一個等級的產(chǎn)品,而抽象工廠模式可生產(chǎn)多個等級的產(chǎn)品。

解決的問題
每個工廠只能創(chuàng)建一類產(chǎn)品

即工廠方法模式的缺點

模式組成
抽象工廠模式同工廠方法模式一樣,也是由抽象工廠、具體工廠、抽象產(chǎn)品和具體產(chǎn)品等 4 個要素構(gòu)成,但抽象工廠中方法個數(shù)不同,抽象產(chǎn)品的個數(shù)也不同?,F(xiàn)在我們來分析其基本結(jié)構(gòu)和實現(xiàn)方法。

使用步驟

  1. 創(chuàng)建抽象工廠類,定義具體工廠的公共接口;
  2. 創(chuàng)建抽象產(chǎn)品族類 ,定義抽象產(chǎn)品的公共接口;
  3. 創(chuàng)建抽象產(chǎn)品類 (繼承抽象產(chǎn)品族類),定義具體產(chǎn)品的公共接口;
  4. 創(chuàng)建具體產(chǎn)品類(繼承抽象產(chǎn)品類) & 定義生產(chǎn)的具體產(chǎn)品;
  5. 創(chuàng)建具體工廠類(繼承抽象工廠類),定義創(chuàng)建對應具體產(chǎn)品實例的方法;

客戶端通過實例化具體的工廠類,并調(diào)用其創(chuàng)建不同目標產(chǎn)品的方法創(chuàng)建不同具體產(chǎn)品類的實例
實例說明
實例概況

  • 背景:隔壁老王有兩間塑料加工廠(A廠僅生產(chǎn)容器類產(chǎn)品;B廠僅生產(chǎn)模具類產(chǎn)品);隨著客戶需求的變化,A廠所在地的客戶需要也模具類產(chǎn)品,B廠所在地的客戶也需要容器類產(chǎn)品;
  • 沖突:沒有資源(資金+租位)在當?shù)胤謩e開設多一家注塑分廠
  • 解決方案:在原有的兩家塑料廠里增設生產(chǎn)需求的功能,即A廠能生產(chǎn)容器+模具產(chǎn)品;B廠間能生產(chǎn)模具+容器產(chǎn)品。

即抽象工廠模式

使用步驟

步驟1: 創(chuàng)建抽象工廠類,定義具體工廠的公共接口。

  1. abstract class Factory{ 
  2.     public abstract AbstractProduct ManufactureContainer(); 
  3.     public abstract AbstractProduct ManufactureMould(); 

步驟2: 創(chuàng)建抽象產(chǎn)品族類 ,定義具體產(chǎn)品的公共接口。

  1. abstract class AbstractProduct{ 
  2.     public abstract void method1(); 

步驟3: 創(chuàng)建抽象產(chǎn)品類 ,定義具體產(chǎn)品的公共接口。

  1. //容器產(chǎn)品抽象類 
  2. abstract class ContainerProduct extends AbstractProduct { 
  3.     @Override 
  4.     public abstract void method1(); 
  5.  
  6. //模具產(chǎn)品抽象類 
  7. abstract class MouldProduct extends AbstractProduct { 
  8.     @Override 
  9.     public abstract void method1(); 

步驟4: 創(chuàng)建具體產(chǎn)品類(繼承抽象產(chǎn)品類), 定義生產(chǎn)的具體產(chǎn)品。

  1. //容器產(chǎn)品A類 
  2. class ContainerProductA extends ContainerProduct{ 
  3.     @Override 
  4.     public void method1() { 
  5.         System.out.println("生產(chǎn)出了容器產(chǎn)品A"); 
  6.     } 
  7.  
  8. //容器產(chǎn)品B類 
  9. class ContainerProductB extends ContainerProduct{ 
  10.     @Override 
  11.     public void method1() { 
  12.         System.out.println("生產(chǎn)出了容器產(chǎn)品B"); 
  13.     } 
  14.  
  15. //模具產(chǎn)品A類 
  16. class MouldProductA extends MouldProduct{ 
  17.  
  18.     @Override 
  19.     public void method1() { 
  20.         System.out.println("生產(chǎn)出了模具產(chǎn)品A"); 
  21.     } 
  22.  
  23. //模具產(chǎn)品B類 
  24. class MouldProductB extends MouldProduct{ 
  25.  
  26.     @Override 
  27.     public void method1() { 
  28.         System.out.println("生產(chǎn)出了模具產(chǎn)品B"); 
  29.     } 

步驟5:創(chuàng)建具體工廠類(繼承抽象工廠類),定義創(chuàng)建對應具體產(chǎn)品實例的方法。

  1. //A廠 - 生產(chǎn)模具+容器產(chǎn)品 
  2. class FactoryA extends Factory{ 
  3.  
  4.     @Override 
  5.     public AbstractProduct ManufactureContainer() { 
  6.         return new ContainerProductA(); 
  7.     } 
  8.  
  9.     @Override 
  10.     public AbstractProduct ManufactureMould() { 
  11.         return new MouldProductA(); 
  12.     } 
  13.  
  14. //B廠 - 生產(chǎn)模具+容器產(chǎn)品 
  15. class FactoryB extends Factory{ 
  16.  
  17.     @Override 
  18.     public AbstractProduct ManufactureContainer() { 
  19.         return new ContainerProductB(); 
  20.     } 
  21.  
  22.     @Override 
  23.     public AbstractProduct ManufactureMould() { 
  24.         return new MouldProductB(); 
  25.     } 

步驟6:客戶端通過實例化具體的工廠類,并調(diào)用其創(chuàng)建不同目標產(chǎn)品的方法創(chuàng)建不同具體產(chǎn)品類的實例。

  1. public class AbstractFactoryPattern { 
  2.  
  3.     public static void main(String[] args){ 
  4.         FactoryA mFactoryA = new FactoryA(); 
  5.         FactoryB mFactoryB = new FactoryB(); 
  6.         //A廠當?shù)乜蛻粜枰萜鳟a(chǎn)品A 
  7.         mFactoryA.ManufactureContainer().method1(); 
  8.         //A廠當?shù)乜蛻粜枰>弋a(chǎn)品A 
  9.         mFactoryA.ManufactureMould().method1(); 
  10.  
  11.         //B廠當?shù)乜蛻粜枰萜鳟a(chǎn)品B 
  12.         mFactoryB.ManufactureContainer().method1(); 
  13.         //B廠當?shù)乜蛻粜枰>弋a(chǎn)品B 
  14.         mFactoryB.ManufactureMould().method1(); 
  15.  
  16.     } 

輸出結(jié)果

  1. 生產(chǎn)出了容器產(chǎn)品A 
  2. 生產(chǎn)出了模具產(chǎn)品A 
  3. 生產(chǎn)出了容器產(chǎn)品B 
  4. 生產(chǎn)出了模具產(chǎn)品B 

優(yōu)點

  • 可以在類的內(nèi)部對產(chǎn)品族中相關(guān)聯(lián)的多等級產(chǎn)品共同管理,而不必專門引入多個新的類來進行管理。
  • 當需要產(chǎn)品族時,抽象工廠可以保證客戶端始終只使用同一個產(chǎn)品的產(chǎn)品組。
  • 抽象工廠增強了程序的可擴展性,當增加一個新的產(chǎn)品族時,不需要修改原代碼,滿足開閉原則。

缺點
當產(chǎn)品族中需要增加一個新的產(chǎn)品時,所有的工廠類都需要進行修改。增加了系統(tǒng)的抽象性和理解難度。

這是因為抽象工廠接口中已經(jīng)確定了可以被創(chuàng)建的產(chǎn)品集合,如果需要添加新產(chǎn)品,此時就必須去修改抽象工廠的接口,這樣就涉及到抽象工廠類的以及所有子類的改變,這樣也就違背了“開發(fā)——封閉”原則。

對于新的產(chǎn)品族符合開-閉原則;對于新的產(chǎn)品種類不符合開-閉原則,這一特性稱為開-閉原則的傾斜性。

應用場景
程序需要處理不同系列的相關(guān)產(chǎn)品,但是您不希望它依賴于這些產(chǎn)品的具體類時,可以使用抽象工廠。

源碼中的應用

  1. #JDK 
  2. java.sql.Connection 
  3. java.sql.Driver 
  4.  
  5. # mybatis 
  6. SqlSessionFactory 

java.sql.Connection

  1. public interface Connection  extends Wrapper, AutoCloseable { 
  2.  //...      
  3.      //返回普通的sql執(zhí)行器 
  4.         Statement createStatement() throws SQLException; 
  5.   //返回具有參數(shù)化預編譯功能的sql執(zhí)行器 
  6.      PreparedStatement prepareStatement(String sql) throws SQLException; 
  7.      //返回可以執(zhí)行存儲過程的sql執(zhí)行器 
  8.         CallableStatement prepareCall(String sql) throws SQLException;    
  9.     //...          

從上面的注釋就可以看出,這就是典型的抽象工廠接口,描述了不同的產(chǎn)品等級Statement、PreparedStatement、CallableStatement,它們都位于抽象接口Statement產(chǎn)品等級結(jié)構(gòu)中。我們可以繼續(xù)尋找該抽象工廠接口的實現(xiàn)類。

以Mysql為例,可以找到Mysql對這個工廠接口的實現(xiàn)類ConnectionImpl,ConnectionImpl并不是直接實現(xiàn)了java.sql.Connection,而是通過實現(xiàn)自己擴展的MySQLConnection接口,該接口也是間接繼承了java.sql.Connection

  1. public class ConnectionImpl extends ConnectionPropertiesImpl implements MySQLConnection { 
  2.  //... 
  3.  
  4.  public java.sql.Statement createStatement() throws SQLException { 
  5.         return createStatement(DEFAULT_RESULT_SET_TYPE, DEFAULT_RESULT_SET_CONCURRENCY); 
  6.     } 
  7.     
  8.  public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException { 
  9.         return prepareStatement(sql, DEFAULT_RESULT_SET_TYPE, DEFAULT_RESULT_SET_CONCURRENCY); 
  10.     } 
  11.      
  12.  public java.sql.CallableStatement prepareCall(String sql) throws SQLException { 
  13.  
  14.         return prepareCall(sql, DEFAULT_RESULT_SET_TYPE, DEFAULT_RESULT_SET_CONCURRENCY); 
  15.     } 
  16.   
  17.  //... 

以createStatement為例,跟蹤其調(diào)用代碼可以看到StatementImpl這個類就是實現(xiàn)了java.sql.Statement的具體產(chǎn)品類

  1. public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { 
  2.     checkClosed(); 
  3.  
  4.     StatementImpl stmt = new StatementImpl(getMultiHostSafeProxy(), this.database); 
  5.     stmt.setResultSetType(resultSetType); 
  6.     stmt.setResultSetConcurrency(resultSetConcurrency); 
  7.  
  8.     return stmt; 

SqlSessionFactory

  1. /** 
  2.  * Creates an {@link SqlSession} out of a connection or a DataSource 
  3.  *  
  4.  * @author Clinton Begin 
  5.  */ 
  6. public interface SqlSessionFactory { 
  7.  
  8.   SqlSession openSession(); 
  9.  
  10.   SqlSession openSession(boolean autoCommit); 
  11.   SqlSession openSession(Connection connection); 
  12.   SqlSession openSession(TransactionIsolationLevel level); 
  13.  
  14.   SqlSession openSession(ExecutorType execType); 
  15.   SqlSession openSession(ExecutorType execType, boolean autoCommit); 
  16.   SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level); 
  17.   SqlSession openSession(ExecutorType execType, Connection connection); 
  18.  
  19.   Configuration getConfiguration(); 
  20.  

SqlSessionFactory也是抽象工廠接口,Configuration和SqlSession都是在不同的產(chǎn)品等級上。通過IDEA工具可以通過UML圖清晰得看到SqlSessionFactory的工廠實現(xiàn)類

以上兩個例子都和數(shù)據(jù)庫操作相關(guān),同樣使用了抽象工廠模式。在jdbc中,客戶端通過Connection工廠獲取到Statement產(chǎn)品對象,然后通過該對象進行增刪改查操作,對于mybatis這種數(shù)據(jù)庫操縱框架而言(底層也是封裝了jdbc api)有異曲同工,通過SeqSessionFactory工廠獲取到SqlSession產(chǎn)品對象,然后進行增刪改查操作。

 

PS:以上代碼提交在 Github :

https://github.com/Niuh-Study/niuh-designpatterns.git

責任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2021-09-29 13:53:17

抽象工廠模式

2021-03-06 22:50:58

設計模式抽象

2022-01-12 13:33:25

工廠模式設計

2009-01-15 10:55:29

JavaScript設計模式抽象工廠

2011-07-28 09:50:58

設計模式

2013-11-26 16:29:22

Android設計模式

2020-12-17 09:38:16

設計模式參數(shù)

2024-03-06 13:19:19

工廠模式Python函數(shù)

2024-09-14 08:24:44

設計模式抽象工廠模式JDK

2020-08-21 07:23:50

工廠模式設計

2011-11-17 16:03:05

Java工廠模式Clojure

2020-09-14 17:26:48

抽象工廠模式

2023-08-07 06:30:15

抽象工廠模式軟件設計模式

2021-07-06 08:59:18

抽象工廠模式

2010-04-19 09:30:00

工廠模式PHP設計模式

2020-10-23 09:40:26

設計模式

2020-11-03 13:05:18

命令模式

2020-11-04 08:54:54

狀態(tài)模式

2024-07-31 08:12:33

2010-10-09 09:25:35

Python工廠模式
點贊
收藏

51CTO技術(shù)棧公眾號