日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

抽象工厂模式_设计模式系列—抽象工厂模式

發(fā)布時(shí)間:2024/1/23 81 豆豆
生活随笔 收集整理的這篇文章主要介紹了 抽象工厂模式_设计模式系列—抽象工厂模式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

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

23種設(shè)計(jì)模式快速記憶的請(qǐng)看上面第一篇,前面說(shuō)完了工廠方法模式,我們發(fā)現(xiàn)工廠方法模式存在一個(gè)嚴(yán)重的問(wèn)題:一個(gè)具體工廠只能創(chuàng)建一類產(chǎn)品 ,而實(shí)際過(guò)程中一個(gè)工廠往往需要生產(chǎn)多類產(chǎn)品。為了解決上述問(wèn)題,可以使用抽象工廠模式,本篇和大家一起來(lái)學(xué)習(xí)抽象工廠模式相關(guān)內(nèi)容。

模式定義

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

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

解決的問(wèn)題

每個(gè)工廠只能創(chuàng)建一類產(chǎn)品

工廠方法模式的缺點(diǎn)

模式組成

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

使用步驟

  • 創(chuàng)建抽象工廠類,定義具體工廠的公共接口;
  • 創(chuàng)建抽象產(chǎn)品族類 ,定義抽象產(chǎn)品的公共接口;
  • 創(chuàng)建抽象產(chǎn)品類 (繼承抽象產(chǎn)品族類),定義具體產(chǎn)品的公共接口;
  • 創(chuàng)建具體產(chǎn)品類(繼承抽象產(chǎn)品類) & 定義生產(chǎn)的具體產(chǎn)品;
  • 創(chuàng)建具體工廠類(繼承抽象工廠類),定義創(chuàng)建對(duì)應(yīng)具體產(chǎn)品實(shí)例的方法;
  • 客戶端通過(guò)實(shí)例化具體的工廠類,并調(diào)用其創(chuàng)建不同目標(biāo)產(chǎn)品的方法創(chuàng)建不同具體產(chǎn)品類的實(shí)例
  • 實(shí)例說(shuō)明

    實(shí)例概況

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

    即抽象工廠模式

    使用步驟

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

    abstract?class?Factory{????public?abstract?AbstractProduct?ManufactureContainer();????public?abstract?AbstractProduct?ManufactureMould();}

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

    abstract?class?AbstractProduct{????public?abstract?void?method1();}

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

    //容器產(chǎn)品抽象類abstract?class?ContainerProduct?extends?AbstractProduct?{????@Override????public?abstract?void?method1();}//模具產(chǎn)品抽象類abstract?class?MouldProduct?extends?AbstractProduct?{????@Override????public?abstract?void?method1();}

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

    //容器產(chǎn)品A類class?ContainerProductA?extends?ContainerProduct{????@Override????public?void?method1()?{????????System.out.println("生產(chǎn)出了容器產(chǎn)品A");????}}//容器產(chǎn)品B類class?ContainerProductB?extends?ContainerProduct{????@Override????public?void?method1()?{????????System.out.println("生產(chǎn)出了容器產(chǎn)品B");????}}//模具產(chǎn)品A類class?MouldProductA?extends?MouldProduct{????@Override????public?void?method1()?{????????System.out.println("生產(chǎn)出了模具產(chǎn)品A");????}}//模具產(chǎn)品B類class?MouldProductB?extends?MouldProduct{????@Override????public?void?method1()?{????????System.out.println("生產(chǎn)出了模具產(chǎn)品B");????}}

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

    //A廠?-?生產(chǎn)模具+容器產(chǎn)品class?FactoryA?extends?Factory{????@Override????public?AbstractProduct?ManufactureContainer()?{????????return?new?ContainerProductA();????}????@Override????public?AbstractProduct?ManufactureMould()?{????????return?new?MouldProductA();????}}//B廠?-?生產(chǎn)模具+容器產(chǎn)品class?FactoryB?extends?Factory{????@Override????public?AbstractProduct?ManufactureContainer()?{????????return?new?ContainerProductB();????}????@Override????public?AbstractProduct?ManufactureMould()?{????????return?new?MouldProductB();????}}

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

    public?class?AbstractFactoryPattern?{????public?static?void?main(String[]?args){????????FactoryA?mFactoryA?=?new?FactoryA();????????FactoryB?mFactoryB?=?new?FactoryB();????????//A廠當(dāng)?shù)乜蛻粜枰萜鳟a(chǎn)品A????????mFactoryA.ManufactureContainer().method1();????????//A廠當(dāng)?shù)乜蛻粜枰>弋a(chǎn)品A????????mFactoryA.ManufactureMould().method1();????????//B廠當(dāng)?shù)乜蛻粜枰萜鳟a(chǎn)品B????????mFactoryB.ManufactureContainer().method1();????????//B廠當(dāng)?shù)乜蛻粜枰>弋a(chǎn)品B????????mFactoryB.ManufactureMould().method1();????}}

    輸出結(jié)果

    生產(chǎn)出了容器產(chǎn)品A生產(chǎn)出了模具產(chǎn)品A生產(chǎn)出了容器產(chǎn)品B生產(chǎn)出了模具產(chǎn)品B

    優(yōu)點(diǎn)

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

    缺點(diǎn)

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

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

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

    應(yīng)用場(chǎng)景

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

    源碼中的應(yīng)用

    #JDKjava.sql.Connectionjava.sql.Driver#?mybatisSqlSessionFactory

    java.sql.Connection

    public?interface?Connection??extends?Wrapper,?AutoCloseable?{?//...??????????//返回普通的sql執(zhí)行器????????Statement?createStatement()?throws?SQLException;??//返回具有參數(shù)化預(yù)編譯功能的sql執(zhí)行器?????PreparedStatement?prepareStatement(String?sql)?throws?SQLException;?????//返回可以執(zhí)行存儲(chǔ)過(guò)程的sql執(zhí)行器????????CallableStatement?prepareCall(String?sql)?throws?SQLException;???????//...?????????}

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

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

    public?class?ConnectionImpl?extends?ConnectionPropertiesImpl?implements?MySQLConnection?{?//...?public?java.sql.Statement?createStatement()?throws?SQLException?{????????return?createStatement(DEFAULT_RESULT_SET_TYPE,?DEFAULT_RESULT_SET_CONCURRENCY);????}????public?java.sql.PreparedStatement?prepareStatement(String?sql)?throws?SQLException?{????????return?prepareStatement(sql,?DEFAULT_RESULT_SET_TYPE,?DEFAULT_RESULT_SET_CONCURRENCY);????}?????public?java.sql.CallableStatement?prepareCall(String?sql)?throws?SQLException?{????????return?prepareCall(sql,?DEFAULT_RESULT_SET_TYPE,?DEFAULT_RESULT_SET_CONCURRENCY);????}??//...}

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

    public?java.sql.Statement?createStatement(int?resultSetType,?int?resultSetConcurrency)?throws?SQLException?{????checkClosed();????StatementImpl?stmt?=?new?StatementImpl(getMultiHostSafeProxy(),?this.database);????stmt.setResultSetType(resultSetType);????stmt.setResultSetConcurrency(resultSetConcurrency);????return?stmt;}

    SqlSessionFactory

    /**?*?Creates?an?{@link?SqlSession}?out?of?a?connection?or?a?DataSource?*??*?@author?Clinton?Begin?*/public?interface?SqlSessionFactory?{??SqlSession?openSession();??SqlSession?openSession(boolean?autoCommit);??SqlSession?openSession(Connection?connection);??SqlSession?openSession(TransactionIsolationLevel?level);??SqlSession?openSession(ExecutorType?execType);??SqlSession?openSession(ExecutorType?execType,?boolean?autoCommit);??SqlSession?openSession(ExecutorType?execType,?TransactionIsolationLevel?level);??SqlSession?openSession(ExecutorType?execType,?Connection?connection);??Configuration?getConfiguration();}

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

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

    PS:以上代碼提交在 Github

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

    文章持續(xù)更新,可以微信搜一搜「 一角錢技術(shù) 」第一時(shí)間閱讀, 本文 GitHub org_hejianhui/JavaStudy 已經(jīng)收錄,歡迎 Star。

    總結(jié)

    以上是生活随笔為你收集整理的抽象工厂模式_设计模式系列—抽象工厂模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。