欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java設(shè)計(jì)模式之工廠方法和抽象工廠

 更新時(shí)間:2022年10月11日 09:05:40   作者:tianClassmate  
本文詳細(xì)講解了Java設(shè)計(jì)模式之工廠方法和抽象工廠,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

全網(wǎng)最詳細(xì)的工廠設(shè)計(jì)模式,本文主要是創(chuàng)建型設(shè)計(jì)模式中的工廠方法和抽象工廠,先由傳統(tǒng)實(shí)現(xiàn)方式引出問題,接著對代碼改進(jìn)到簡單工廠,后擴(kuò)展到工廠方法,最后是抽象工廠模式,文中包括概念理解和相關(guān)實(shí)現(xiàn)代碼。

讀者可以拉取完整代碼本地學(xué)習(xí),實(shí)現(xiàn)代碼均測試通過上傳到碼云本地源碼下載。

一、引出問題

如果有一個(gè)客戶老王,需要購買產(chǎn)品,產(chǎn)品分別是A、B、C。

如果用傳統(tǒng)方法實(shí)現(xiàn),分別定義A、B、C三個(gè)類,再分別創(chuàng)建他們所屬的方法。

在客戶對象中再分別調(diào)用他們的方法。

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;
}

如果我們需要再增加一個(gè)產(chǎn)品D,就需要判斷再增加一個(gè)分支,然后在分支里面創(chuàng)建產(chǎn)品對象,調(diào)用產(chǎn)品D的方法。

這樣代碼的維護(hù)性是極差的,查看我們的軟件設(shè)計(jì)七大原則,很明顯,這違反了開閉原則、依賴倒置原則.

如果又有個(gè)客戶小王,那么小王也必須依賴每個(gè)產(chǎn)品類,這樣就顯得冗雜。

二、簡單工廠(靜態(tài)工廠)

簡單工廠(靜態(tài)工廠)模式就應(yīng)用而生了。

如果我們將產(chǎn)品A、B、C抽象出來一個(gè)父類,再專門創(chuàng)建一個(gè)工廠類,在客戶購買產(chǎn)品時(shí),只需要傳入產(chǎn)品的類型,由工廠去創(chuàng)建產(chǎn)品。

簡單工廠模式中包含如下角色:

Factory:工廠角色

? 工廠角色負(fù)責(zé)實(shí)現(xiàn)創(chuàng)建所有實(shí)例的內(nèi)部邏輯。

Product:抽象產(chǎn)品角色

? 抽象產(chǎn)品角色是所創(chuàng)建的所有對象的父類,負(fù)責(zé)描述所有實(shí)例所共有的公共接口。

ConcreteProduct:具體產(chǎn)品角色

? 具體產(chǎn)品角色是創(chuàng)建目標(biāo),所有創(chuàng)建的對象都充當(dāng)這個(gè)角色的某個(gè)具體類的實(shí)例。

看看我們對原始實(shí)現(xiàn)方式后的代碼。

產(chǎn)品抽象父類:

/**
 * @author tcy
 * @Date 28-07-2022
 */
public class Product {

    public void common(){
        System.out.println("這是產(chǎn)品父類公共方法...");
    }


}

產(chǎn)品A:

/**
 * @author tcy
 * @Date 28-07-2022
 */
public class ProductA extends Product{

    public void common(){
        System.out.println("這是產(chǎn)品A方法...");
    }

}

產(chǎn)品B:

/**
 * @author tcy
 * @Date 28-07-2022
 */
public class ProductB extends Product{

    public void common(){
        System.out.println("這是產(chǎn)品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);

       //調(diào)用每個(gè)產(chǎn)出相應(yīng)的方法
        product.common();
        System.out.println(product.getClass());
        return product;
    }

    public static void main(String[] args) {
        Client client=new Client(new SimpleFactory());
        client.orderProduct("A");
    }

}

這樣簡單工廠模式就實(shí)現(xiàn)了,這樣的話老王和具體的產(chǎn)品就很好的解耦了,也不需要老王再依賴具體產(chǎn)品類,依賴倒置問題就很好的解決了。

如果增加一個(gè)產(chǎn)品D,需要再重新定義一個(gè)D類,實(shí)現(xiàn)product接口,而后在工廠類中增加一個(gè)分支結(jié)構(gòu)。

顯而易見這樣實(shí)現(xiàn),缺陷依然存在:

1、工廠類集中了所有產(chǎn)品創(chuàng)建邏輯,職責(zé)過重,一旦發(fā)生異常,整個(gè)系統(tǒng)將受影響。
2、使用簡單工廠模式將會(huì)增加系統(tǒng)中類的個(gè)數(shù),在一定程序上增加了系統(tǒng)的復(fù)雜度和理解難度。
3、系統(tǒng)擴(kuò)展困難,一旦增加新產(chǎn)品不得不修改工廠邏輯,在產(chǎn)品類型較多時(shí),可能造成邏輯過于復(fù)雜。
4、簡單工廠模式由于使用了靜態(tài)工廠方法,造成工廠角色無法形成基于繼承的等級(jí)結(jié)構(gòu)。

這種方法只是一種編碼方式,并不輸入設(shè)計(jì)模式的一種,且局限于產(chǎn)品種類較少。

三、工廠方法

在簡單工廠中老王需要具體的產(chǎn)品,就在他自己的類中去創(chuàng)建需要的產(chǎn)品,老王雖然不依賴具體產(chǎn)品,但老王現(xiàn)在需要依賴工廠實(shí)現(xiàn)類了。

簡單工廠是將產(chǎn)品類抽象化,具體的產(chǎn)品由工廠類去實(shí)現(xiàn)。

如果我們將工廠類也抽象化,那就引出了我們今天第一個(gè)設(shè)計(jì)模式——工廠方法。

工廠方法有四個(gè)角色:

1、抽象工廠(Abstract Factory):提供了創(chuàng)建產(chǎn)品的接口,調(diào)用者通過它訪問具體工廠的工廠方法 createProduct() 來創(chuàng)建產(chǎn)品。
2、具體工廠(ConcreteFactory):主要是實(shí)現(xiàn)抽象工廠中的抽象方法,完成具體產(chǎn)品的創(chuàng)建。
3、抽象產(chǎn)品(Product):定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能。
4、具體產(chǎn)品(ConcreteProduct):實(shí)現(xiàn)了抽象產(chǎn)品角色所定義的接口,由具體工廠來創(chuàng)建,它同具體工廠之間一一對應(yīng)。

我們對簡單工廠代碼進(jìn)行改造。

抽象產(chǎn)品父類、產(chǎn)品A類、產(chǎn)品B類保持不變。重點(diǎn)看工廠類

抽象工廠類:

/**
 * @author tcy
 * @Date 28-07-2022
 */

public abstract class AbstractFactory {

    public abstract Product createProduct(String orderType);
}

具體實(shí)現(xiàn)工廠A類:

/**
 * @author tcy
 * @Date 28-07-2022
 */
public class ConcreteFactoryA extends AbstractFactory{
    @Override
    public Product createProduct(String orderType) {
        System.out.println("參數(shù)為:"+orderType);
        return new ProductA();
    }
}

具體實(shí)現(xiàn)工廠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);

       //調(diào)用每個(gè)產(chǎn)出相應(yīng)的方法
        product.common();
        System.out.println(product.getClass());
        return product;
    }

    public static void main(String[] args) {
        Client client=new Client(new ConcreteFactoryA());
        client.orderProduct("A");
    }

}

這樣的好處就在于老王只管他要關(guān)注的抽象工廠,具體是哪個(gè)工廠實(shí)現(xiàn)類生產(chǎn)產(chǎn)品,老王也不需要關(guān)注。

典型的解耦框架。高層模塊只需要知道產(chǎn)品的抽象類,無須關(guān)心其他實(shí)現(xiàn)類,滿足迪米特法則、依賴倒置原則和里氏替換原則。

缺點(diǎn)也是顯而易見的:

  • 類的個(gè)數(shù)容易過多,增加復(fù)雜度。
  • 考慮到系統(tǒng)的可擴(kuò)展性,需要引入抽象層,在客戶端代碼中均使用抽象層進(jìn)行定義,增加了系統(tǒng)的抽象性和理解難度。
  • 抽象產(chǎn)品只能生產(chǎn)一種產(chǎn)品。

如果對工廠方法依然一知半解的話,接著往下看工廠方法的一個(gè)典型實(shí)現(xiàn)

在JDK中對工廠方法有大量的運(yùn)用,其中比較典型的是

new ArrayList<>().iterator();

我們知道集合的一個(gè)大分支依賴的是Collection接口,我們以ArrayList作為舉例。

Collection接口相當(dāng)于產(chǎn)品的抽象父類,ArrayList相當(dāng)于具體產(chǎn)品。

Iterator是一個(gè)抽象工廠,在ArrayList中有一個(gè)Itr內(nèi)部類實(shí)現(xiàn)了Iterator接口

當(dāng)我們調(diào)用集合的iterator()方法遍歷對象時(shí),就會(huì)調(diào)用各自類的具體實(shí)現(xiàn)方法。

四、抽象工廠

有一天,產(chǎn)品A、B、C升級(jí)改造了,三種產(chǎn)品分別有紅色和藍(lán)色,如果還用工廠方法的話,那簡直是個(gè)災(zāi)難,具體工廠實(shí)現(xiàn)類需要六個(gè)。

就引出我們今天的第二個(gè)設(shè)計(jì)模式——抽象工廠。

抽象工廠模式(Abstract Factory Pattern):提供一個(gè)接口,用于創(chuàng)建創(chuàng)建一系列相關(guān)或相互依賴對象的家族,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式,屬于對象創(chuàng)建型模式。

抽象工廠模式與工廠方法模式區(qū)別在于,工廠方法模式針對的是一個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)。

而抽象工廠模式則需要面對多個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)(各種顏色),一個(gè)工廠等級(jí)結(jié)構(gòu)可以負(fù)責(zé)多個(gè)不同產(chǎn)品等級(jí)結(jié)構(gòu)(不同顏色)中的產(chǎn)品對象的創(chuàng)建 。

抽象工廠依然是四個(gè)角色:

  • AbstractFactory:抽象工廠

  • ConcreteFactory:具體工廠

  • AbstractProduct:抽象產(chǎn)品

  • Product:具體產(chǎn)品

    我們開始改造工廠方法代碼,既然是要把產(chǎn)品都分成一組,那理應(yīng)把產(chǎn)品A、B、C都抽象出來,再讓工廠類去實(shí)現(xiàn)各個(gè)產(chǎn)品的不同顏色,也就是概念中的——用于創(chuàng)建創(chuàng)建一系列相關(guān)或相互依賴對象的家族。

接口看改造后的代碼:

產(chǎn)品抽象類:

/**
 * @author tcy
 * @Date 28-07-2022
 */
public interface Product {

    public void common();

}

產(chǎn)品抽象A家族類:

/**
 * @author tcy
 * @Date 28-07-2022
 */
public abstract class ProductA implements Product {

    public abstract void common();

}

產(chǎn)品抽象B家族類:

/**
 * @author tcy
 * @Date 28-07-2022
 */
public abstract class ProductB implements Product {

    public abstract void common();
}

具體紅色產(chǎn)品A類:

/**
 * @author tcy
 * @Date 28-07-2022
 */
public class RedProductA extends ProductA{
    @Override
    public void common() {
        System.out.println("這是紅色的產(chǎn)品A");
    }
}

具體藍(lán)色產(chǎn)品A類:

/**
 * @author tcy
 * @Date 28-07-2022
 */
public class BlueProductA extends ProductA {

    @Override
    public void common() {
        System.out.println("這是藍(lán)色的產(chǎn)品A");
    }
}

抽象A家族工廠類:

/**
 * @author tcy
 * @Date 28-07-2022
 */

public interface AbstractProductFactory {

    public ProductA createProduct(String orderType);
}

實(shí)現(xiàn)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);

       //調(diào)用每個(gè)產(chǎn)出相應(yīng)的方法
        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的產(chǎn)品家族類(紅、藍(lán))都實(shí)現(xiàn),抽象工廠模式隔離了具體類的生成,使得老王并不需要知道什么產(chǎn)品被創(chuàng)建,從具體的產(chǎn)品解耦出來。

  • 當(dāng)一個(gè)產(chǎn)品族中的多個(gè)對象被設(shè)計(jì)成一起工作時(shí),它能夠保證客戶端始終只使用同一個(gè)產(chǎn)品族中的對象。

如果要增加新產(chǎn)品、和新工廠很容易,如果再增加一個(gè)等級(jí)(顏色)代碼修改起來就很痛苦了。

抽象工廠模式在Spring中有大量的運(yùn)用。

比較典型的是,BeanFactory 是用于管理 Bean 的一個(gè)工廠,所有工廠都是 BeanFactory 的子類。這樣我們可以通過 IOC 容器來管理訪問 Bean,根據(jù)不同的策略調(diào)用 getBean() 方法,從而獲得具體對象。

BeanFactory 的子類主要有

ClassPathXmlApplicationContext、

XmlWebApplicationContext、

StaticWebApplicationContext、

StaticApplicationContext。

在 Spring 中,DefaultListableBeanFactory 實(shí)現(xiàn)了所有工廠的公共邏輯。

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接

相關(guān)文章

  • SpringBoot使用JDBC獲取相關(guān)的數(shù)據(jù)方法

    SpringBoot使用JDBC獲取相關(guān)的數(shù)據(jù)方法

    這篇文章主要介紹了SpringBoot使用JDBC獲取相關(guān)的數(shù)據(jù)方法,JDBC與數(shù)據(jù)庫建立連接、發(fā)送 操作數(shù)據(jù)庫的語句并處理結(jié)果,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-03-03
  • Servlet+JDBC實(shí)現(xiàn)登陸功能的小例子(帶驗(yàn)證碼)

    Servlet+JDBC實(shí)現(xiàn)登陸功能的小例子(帶驗(yàn)證碼)

    這篇文章主要介紹了Servlet+JDBC實(shí)現(xiàn)登陸功能的小例子(帶驗(yàn)證碼),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Java中的同步與異步詳細(xì)介紹

    Java中的同步與異步詳細(xì)介紹

    這篇文章主要介紹了Java中的同步與異步詳細(xì)介紹,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • springboot集成nacos讀取nacos配置數(shù)據(jù)的原理

    springboot集成nacos讀取nacos配置數(shù)據(jù)的原理

    這篇文章主要介紹了springboot集成nacos讀取nacos配置數(shù)據(jù)的原理,文中有詳細(xì)的代碼流程,對大家學(xué)習(xí)springboot集成nacos有一定的幫助,需要的朋友可以參考下
    2023-05-05
  • Java多線程正確使用倒計(jì)時(shí)協(xié)調(diào)器CountDownLatch方法詳解

    Java多線程正確使用倒計(jì)時(shí)協(xié)調(diào)器CountDownLatch方法詳解

    這篇文章主要為大家介紹了Java多線程倒計(jì)時(shí)協(xié)調(diào)器CountDownLatch的正確使用方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Java注解簡介和使用詳細(xì)講解

    Java注解簡介和使用詳細(xì)講解

    Java 語言中的類、構(gòu)造器、方法、成員變量、參數(shù)等都可以被注解進(jìn)行標(biāo)注,這篇文章主要介紹了Java注解的介紹和使用詳細(xì)講解,需要的朋友可以參考下
    2023-02-02
  • SpringBoot中整合knife4j接口文檔的實(shí)踐

    SpringBoot中整合knife4j接口文檔的實(shí)踐

    這篇文章主要介紹了SpringBoot中整合knife4j接口文檔的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Spring Boot實(shí)現(xiàn)Undertow服務(wù)器同時(shí)支持HTTP2、HTTPS的方法

    Spring Boot實(shí)現(xiàn)Undertow服務(wù)器同時(shí)支持HTTP2、HTTPS的方法

    這篇文章考慮如何讓Spring Boot應(yīng)用程序同時(shí)支持HTTP和HTTPS兩種協(xié)議。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • SpringBoot解析JSON數(shù)據(jù)的三種方案

    SpringBoot解析JSON數(shù)據(jù)的三種方案

    JSON(JavaScript Object Notation) 是一種輕量級(jí)的數(shù)據(jù)交換格式,易于人閱讀和編寫,同時(shí)也易于機(jī)器解析和生成,本文給大家介紹了SpringBoot解析JSON數(shù)據(jù)的三種方案,需要的朋友可以參考下
    2024-03-03
  • springboot從application.properties中注入list,?map方式

    springboot從application.properties中注入list,?map方式

    這篇文章主要介紹了springboot從application.properties中注入list,map方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11

最新評(píng)論