最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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、使用簡單工廠模式將會增加系統(tǒng)中類的個(gè)數(shù),在一定程序上增加了系統(tǒng)的復(fù)雜度和理解難度。
3、系統(tǒng)擴(kuò)展困難,一旦增加新產(chǎn)品不得不修改工廠邏輯,在產(chǎn)品類型較多時(shí),可能造成邏輯過于復(fù)雜。
4、簡單工廠模式由于使用了靜態(tài)工廠方法,造成工廠角色無法形成基于繼承的等級結(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í),就會調(diào)用各自類的具體實(shí)現(xiàn)方法。

四、抽象工廠

有一天,產(chǎn)品A、B、C升級改造了,三種產(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)品等級結(jié)構(gòu)。

而抽象工廠模式則需要面對多個(gè)產(chǎn)品等級結(jié)構(gòu)(各種顏色),一個(gè)工廠等級結(jié)構(gòu)可以負(fù)責(zé)多個(gè)不同產(chǎn)品等級結(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è)等級(顏色)代碼修改起來就很痛苦了。

抽象工廠模式在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)文章

  • Java實(shí)現(xiàn)的簡單音樂播放器功能示例

    Java實(shí)現(xiàn)的簡單音樂播放器功能示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的簡單音樂播放器功能,涉及java針對多媒體文件相關(guān)載入、播放相關(guān)操作技巧,需要的朋友可以參考下
    2019-02-02
  • Spring BPP中如何優(yōu)雅的創(chuàng)建動態(tài)代理Bean詳解

    Spring BPP中如何優(yōu)雅的創(chuàng)建動態(tài)代理Bean詳解

    這篇文章主要給大家介紹了關(guān)于Spring BPP中如何優(yōu)雅的創(chuàng)建動態(tài)代理Bean的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 詳解java構(gòu)建者模式Builder

    詳解java構(gòu)建者模式Builder

    這篇文章主要介紹了java構(gòu)建者模式Builder,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 詳解Spring Cloud 斷路器集群監(jiān)控(Turbine)

    詳解Spring Cloud 斷路器集群監(jiān)控(Turbine)

    這篇文章主要介紹了詳解Spring Cloud 斷路器集群監(jiān)控(Turbine),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • JavaWeb中的Cookie和Session解讀

    JavaWeb中的Cookie和Session解讀

    這篇文章主要介紹了JavaWeb中的Cookie和Session解讀,Cookie是servlet發(fā)送到Web瀏覽器的少量信息,該信息由瀏覽器保存,然后發(fā)送回服務(wù)器,一般情況下,Cookie是以鍵值對進(jìn)行表示的,Cookie的值可以唯一地標(biāo)識客戶端,因此Cookie常用于會話管理,需要的朋友可以參考下
    2023-10-10
  • Java實(shí)現(xiàn)最小高度樹

    Java實(shí)現(xiàn)最小高度樹

    本文主要介紹了Java實(shí)現(xiàn)最小高度樹,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 基于java Springboot實(shí)現(xiàn)教務(wù)管理系統(tǒng)詳解

    基于java Springboot實(shí)現(xiàn)教務(wù)管理系統(tǒng)詳解

    這篇文章主要介紹了Java 實(shí)現(xiàn)簡易教務(wù)管理系統(tǒng)的代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • SpringBoot中定時(shí)任務(wù)@Scheduled的多線程使用詳解

    SpringBoot中定時(shí)任務(wù)@Scheduled的多線程使用詳解

    這篇文章主要為大家詳細(xì)介紹了pring Boot定時(shí)任務(wù)@Scheduled的多線程原理以及如何加入線程池來處理定時(shí)任務(wù),感興趣的可以了解一下
    2023-04-04
  • idea sql的xml文件出現(xiàn)紅色警告符的處理方式

    idea sql的xml文件出現(xiàn)紅色警告符的處理方式

    這篇文章主要介紹了idea sql的xml文件出現(xiàn)紅色警告符處理方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • 使用res:bean屬性復(fù)制避免null值覆蓋版本

    使用res:bean屬性復(fù)制避免null值覆蓋版本

    這篇文章主要介紹了使用res:bean屬性復(fù)制避免null值覆蓋版本的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評論

富阳市| 大埔县| 通榆县| 买车| 分宜县| 安远县| 启东市| 蕉岭县| 余庆县| 抚远县| 客服| 马关县| 治多县| 屏南县| 容城县| 衡南县| 迁安市| 朔州市| 凉城县| 随州市| 太仆寺旗| 沙坪坝区| 大英县| 平塘县| 仙居县| 万年县| 石景山区| 北流市| 阜阳市| 朝阳市| 普定县| 吐鲁番市| 武强县| 潍坊市| 思南县| 安多县| 汝阳县| 长乐市| 通州区| 平顺县| 西乌珠穆沁旗|