創(chuàng)建型模式 - 抽象工廠模式

0x01 前言

??繼上一篇文章所述,抽象工廠模式(Abstract Factory Pattern)是圍繞一個(gè)超級工廠創(chuàng)建其他工廠。該超級工廠又稱為其他工廠的工廠。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式。

??在抽象工廠模式中,接口是負(fù)責(zé)創(chuàng)建一個(gè)相關(guān)對象的工廠,不需要顯式指定它們的類。每個(gè)生成的工廠都能按照工廠模式提供對象。

0x02 簡介

意圖:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無需指定它們具體的類。

主要解決:主要解決接口選擇的問題。

何時(shí)使用:系統(tǒng)的產(chǎn)品有多于一個(gè)的產(chǎn)品族,而系統(tǒng)只消費(fèi)其中某一族的產(chǎn)品。

如何解決:在一個(gè)產(chǎn)品族里面,定義多個(gè)產(chǎn)品。

關(guān)鍵代碼:在一個(gè)工廠里聚合多個(gè)同類產(chǎn)品。

應(yīng)用實(shí)例:工作了,為了參加一些聚會(huì),肯定有兩套或多套衣服吧,比如說有商務(wù)裝(成套,一系列具體產(chǎn)品)、時(shí)尚裝(成套,一系列具體產(chǎn)品),甚至對于一個(gè)家庭來說,可能有商務(wù)女裝、商務(wù)男裝、時(shí)尚女裝、時(shí)尚男裝,這些也都是成套的,即一系列具體產(chǎn)品。假設(shè)一種情況(現(xiàn)實(shí)中是不存在的,要不然,沒法進(jìn)入共產(chǎn)主義了,但有利于說明抽象工廠模式),在您的家中,某一個(gè)衣柜(具體工廠)只能存放某一種這樣的衣服(成套,一系列具體產(chǎn)品),每次拿這種成套的衣服時(shí)也自然要從這個(gè)衣柜中取出了。用 OO 的思想(面向?qū)ο螅┤ダ斫?,所有的衣柜(具體工廠)都是衣柜類的(抽象工廠)某一個(gè),而每一件成套的衣服又包括具體的上衣(某一具體產(chǎn)品),褲子(某一具體產(chǎn)品),這些具體的上衣其實(shí)也都是上衣(抽象產(chǎn)品),具體的褲子也都是褲子(另一個(gè)抽象產(chǎn)品)。

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

缺點(diǎn):產(chǎn)品族擴(kuò)展非常困難,要增加一個(gè)系列的某一產(chǎn)品,既要在抽象的 Creator 里加代碼,又要在具體的里面加代碼。

使用場景: 1、QQ 換皮膚,一整套一起換。 2、生成不同操作系統(tǒng)的程序。

注意事項(xiàng):產(chǎn)品族難擴(kuò)展,產(chǎn)品等級易擴(kuò)展。

0x03 設(shè)計(jì)概述

??抽象工廠模式是工廠方法模式的升級版本,他用來創(chuàng)建一組相關(guān)或者相互依賴的對象。

??抽象工廠模式時(shí)代:隨著客戶的要求越來越高,需要定制不同組合的電腦。例如聯(lián)想 Y 系列,華碩 G 系列,聯(lián)想 Y 配備性能級顯卡,聯(lián)想 G 配備發(fā)燒級顯卡。那么并不需要?jiǎng)?chuàng)辦一個(gè)生產(chǎn)聯(lián)想 Y 性能級顯卡電腦的工廠、華碩 G 發(fā)燒級顯卡電腦的工廠。而僅僅是抽象一個(gè)工廠,用來生產(chǎn)聯(lián)想 Y 電腦、華碩 G 電腦、性能級顯卡、發(fā)燒級顯卡,然后組合就形成產(chǎn)品。

0x04 具體實(shí)現(xiàn)

抽象工廠時(shí)代
項(xiàng)目結(jié)構(gòu)圖
項(xiàng)目結(jié)構(gòu)圖.PNG
產(chǎn)品類

??為產(chǎn)品顯卡創(chuàng)建接口。

// factory_pattern.abstract_factory.product.IGraphics
public interface IGraphics {
    void getGraphics(String series);
}

??為產(chǎn)品電腦創(chuàng)建接口。

// factory_pattern.abstract_factory.product.IComputer
public interface IComputer {
    void getComputer(String brand);
}

??拓展上述接口,采用需要組合的方式生產(chǎn)產(chǎn)品,所以將類進(jìn)行細(xì)分拓展接口。

??拓展顯卡接口 IGraphics ,定義性能級顯卡類 PerformanceGraphics 。

// factory_pattern.abstract_factory.product.impl.PerformanceGraphics
public class PerformanceGraphics implements IGraphics {
    @Override
    public void getGraphics(String series) {
        System.out.println("研發(fā)一個(gè) " + series + " 顯卡");
    }
}

??拓展顯卡接口 IGraphics ,定義發(fā)燒級顯卡類 FeverGraphics 。

// factory_pattern.abstract_factory.product.impl.FeverGraphics
public class FeverGraphics implements IGraphics {
    @Override
    public void getGraphics(String series) {
        System.out.println("制造一個(gè) " + series + " 顯卡");
    }
}

??拓展電腦接口 IComputer ,定義聯(lián)想電腦類 LenovoComputer 。

// factory_pattern.abstract_factory.product.impl.LenovoComputer
public class LenovoComputer implements IComputer {
    @Override
    public void getComputer(String brand) {
        System.out.println("制造一臺(tái) " + brand + " 筆記本電腦");
    }
}

??拓展電腦接口 IComputer ,定義華碩電腦類 AsusComputer 。

// factory_pattern.abstract_factory.product.impl.AsusComputer
public class AsusComputer implements IComputer {
    @Override
    public void getComputer(String brand) {
        System.out.println("研發(fā)一臺(tái) " + brand + " 臺(tái)式電腦");
    }
}
工廠類

??為 Computer 和 Graphics 對象創(chuàng)建接口 IAbstractFactory 來獲取工廠。

// factory_pattern.abstract_factory.factory.IAbstractFactory
public interface IAbstractFactory {
    IComputer createComputer(String brand);
    IGraphics createGraphics(String series);
}

??創(chuàng)建擴(kuò)展了 IAbstractFactory 的工廠接口,基于給定的信息生成實(shí)體類的對象。

// factory_pattern.abstract_factory.factory.impl.GraphicsFactroy
public class GraphicsFactroy implements IAbstractFactory {
    @Override
    public IComputer createComputer(String brand) {
        return null;
    }
    @Override
    public IGraphics createGraphics(String series) {
        switch (series) {
            case "Performance" :
                return new PerformanceGraphics();
            case "Fever" :
                return new FeverGraphics();
            default :
                throw new IllegalArgumentException();
        }
    }
}
// factory_pattern.abstract_factory.factory.impl.ComputerFactory
public class ComputerFactory implements IAbstractFactory {
    @Override
    public IComputer createComputer(String brand) {
        switch (brand) {
            case "Lenovo" :
                return new LenovoComputer();
            case "Asus" :
                return new AsusComputer();
            default :
                throw new IllegalArgumentException();
        }
    }
    @Override
    public IGraphics createGraphics(String series) {
        return null;
    }
}

??創(chuàng)建一個(gè)工廠創(chuàng)造器 / 生成器類,通過傳遞品牌或型號來獲取工廠。

// factory_pattern.abstract_factory.factory.impl.FactoryProducer
public class FactoryProducer {
    public static IAbstractFactory getFactory(String choice){
        switch (choice) {
            case "Computer" :
                return new ComputerFactory();
            case "Graphics" :
                return new GraphicsFactroy();
            default :
                throw new IllegalArgumentException();
        }
    }
}
用戶類

??使用 FactoryProducer 來獲取 IAbstractFactory,通過傳遞類型信息來獲取實(shí)體類的對象。

// factory_pattern.abstract_factory.user.ComputerTest
public class ComputerTest {
    @Test
    public void testGetLenovoPerformanceComputer() {
        IAbstractFactory computerFactory = FactoryProducer.getFactory("Computer");
        IComputer lenPC = computerFactory.createComputer("Lenovo");
        IAbstractFactory graphicsFactory = FactoryProducer.getFactory("Graphics");
        IGraphics lenPer = graphicsFactory.createGraphics("Performance");
        lenPC.getComputer("Lenovo");
        lenPer.getGraphics("Performance");
    }
    @Test
    public void testGetAsusFeverComputer() {
        IAbstractFactory computerFactory = FactoryProducer.getFactory("Computer");
        IComputer lenPC = computerFactory.createComputer("Asus");
        IAbstractFactory graphicsFactory = FactoryProducer.getFactory("Graphics");
        IGraphics lenPer = graphicsFactory.createGraphics("Fever");
        lenPC.getComputer("Asus");
        lenPer.getGraphics("Fever");
    }
}
驗(yàn)證輸出

testGetLenovoPerformanceComputer

制造一臺(tái) Lenovo 筆記本電腦
研發(fā)一個(gè) Performance 顯卡

testGetAsusFeverComputer

研發(fā)一臺(tái) Asus 臺(tái)式電腦
制造一個(gè) Fever 顯卡

0x05 總結(jié)

??無論是簡單工廠,工廠方法模式,還是抽象工廠模式,他們都屬于工廠模式,在形式和特點(diǎn)上也是極為相似的,他們的最終目的都是為了解耦。在使用時(shí),我們不必去在意這個(gè)模式到底工廠方法模式還是抽象工廠模式,因?yàn)樗麄冎g的演變常常是令人琢磨不透的。經(jīng)常你會(huì)發(fā)現(xiàn),明明使用的工廠方法模式,當(dāng)新需求來臨,稍加修改,加入了一個(gè)新方法后,由于類中的產(chǎn)品構(gòu)成了不同等級結(jié)構(gòu)中的產(chǎn)品族,它就變成抽象工廠模式了。而對于抽象工廠模式,當(dāng)減少一個(gè)方法使的提供的產(chǎn)品不再構(gòu)成產(chǎn)品族之后,它就演變成了工廠方法模式。

??所以,在使用工廠模式時(shí),只需要關(guān)心降低耦合度的目的是否達(dá)到了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容