設(shè)計模式三十六計之抽象工廠模式(Abstract Factory)

設(shè)計模式三十六計之抽象工廠模式(Abstract Factory)

1.設(shè)計意圖

提供一個接口,用于創(chuàng)建相關(guān)或者從屬對象的族佃迄,而不是指定他們的具體類地淀。以下以生產(chǎn)計算機為例給出UML類圖:


UML-類圖

2.演示案例

假設(shè)我們要生產(chǎn)一臺計算機(廣義的)梧疲,一臺計算機有一些共同的物件擦耀。小型計算機(以手機為例)需要有觸控屏、微處理器和小型化的內(nèi)存條榕酒。大型計算機(以PC機為例)需要有顯示屏胚膊、多核處理器和內(nèi)存條故俐。計算機的各個部件存在著相互依賴關(guān)系。

簡而言之

抽象工廠即工廠的工廠紊婉,它將單獨但相關(guān)/依賴的工廠分組在一起而不是指定具體類別的工廠药版。

維基百科:

抽象工廠模式提供了一種方法來封裝一組具有共同主題的單個工廠,而不指定它們的具體類喻犁。

3.代碼示例

以上述的生產(chǎn)計算機為案例槽片,首選我們需要定義一些部件接口并實現(xiàn)這些部件接口

Memory.java

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:23
 * @modify by :
 * @info:[內(nèi)存接口類]
 * @since:
 */
public interface Memory {

    String getDescription();
}

Screen.java

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:22
 * @modify by :
 * @info:[屏幕接口類]
 * @since:
 */
public interface Screen {

    String getDescription();
}

Processor.java

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:24
 * @modify by :
 * @info:[處理器接口類]
 * @since:
 */
public interface Processor {

    String getDescription();
}

PhoneMemory.java

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:28
 * @modify by :
 * @info:[手機內(nèi)存類]
 * @since:
 */
public class PhoneMemory implements Memory{

    static final String DESCRIPTION = "This is phone memory";

    @Override
    public String getDescription() {
        return DESCRIPTION;
    }
}

PhoneScreen.java

package com.ramostear.pattern.abstractfactory;
/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:26
 * @modify by :
 * @info:[手機屏幕類]
 * @since:
 */
public class PhoneScreen implements Screen{

    static final String DESCRIPTION = "This is phone screen";

    @Override
    public String getDescription() {
        return DESCRIPTION;
    }
}

PhoneProcessor.java

package com.ramostear.pattern.abstractfactory;
/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:29
 * @modify by :
 * @info:[手機處理器類]
 * @since:
 */
public class PhoneProcessor implements Processor{

    static final String DESCRIPTION = "This is phone processor";

    @Override
    public String getDescription() {
        return DESCRIPTION;
    }
}

ComputerMomory.java

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:38
 * @modify by :
 * @info:[電腦內(nèi)存條]
 * @since:
 */
public class ComputerMemory implements Memory{

    static final String DESCRIPTION = "This is computer memory";

    @Override
    public String getDescription() {
        return DESCRIPTION;
    }
}

ComputerScreen.java

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:36
 * @modify by :
 * @info:[電腦屏幕]
 * @since:
 */
public class ComputerScreen implements Screen{

    static final String DESCRIPTION = "This is computer screen";

    @Override
    public String getDescription() {
        return DESCRIPTION;
    }
}

ComputerProcessor.java

package com.ramostear.pattern.abstractfactory;
/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:39
 * @modify by :
 * @info:[電腦處理器]
 * @since:
 */
public class ComputerProcessor implements Processor{

    static final String DESCRIPTION = "This is computer processor";

    @Override
    public String getDescription() {
        return DESCRIPTION;
    }
}

然后,我們定義一個抽象的電子產(chǎn)品生產(chǎn)工廠類并創(chuàng)建兩個它的實現(xiàn)類:
ElectronicFactory.java

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:32
 * @modify by :
 * @info:[電子設(shè)備生產(chǎn)工廠接口類]
 * @since:
 */
public interface ElectronicFactory {
    /**
     * 生產(chǎn)屏幕
     * @return
     */
    Screen produceScreen();

    /**
     * 生產(chǎn)內(nèi)存條
     * @return
     */
    Memory produceMemory();

    /**
     * 生產(chǎn)處理器
     * @return
     */
    Processor produceProcessor();

}

ComputerFactory.java

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:40
 * @modify by :
 * @info:[電腦生產(chǎn)工廠]
 * @since:
 */
public class ComputerFactory implements ElectronicFactory{

    @Override
    public Screen produceScreen() {
        return new ComputerScreen();
    }

    @Override
    public Memory produceMemory() {
        return new ComputerMemory();
    }

    @Override
    public Processor produceProcessor() {
        return new ComputerProcessor();
    }
}

PhoneFactory.java

package com.ramostear.pattern.abstractfactory;
/**
 * @author ramostear
 * @create-time 2019/1/5 0005-2:35
 * @modify by :
 * @info:[手機生產(chǎn)工廠]
 * @since:
 */
public class PhoneFactory implements ElectronicFactory{


    @Override
    public Screen produceScreen() {
        return new PhoneScreen();
    }

    @Override
    public Memory produceMemory() {
        return new PhoneMemory();
    }

    @Override
    public Processor produceProcessor() {
        return new PhoneProcessor();
    }
}

現(xiàn)在我們已經(jīng)擁有了一個抽象的工廠株汉,它可以讓我們生產(chǎn)相關(guān)的電子產(chǎn)品部件筐乳,即手機工廠可以生產(chǎn)手機屏幕、手機處理器和手機內(nèi)存條乔妈,同樣電腦工廠可以生產(chǎn)電腦顯示器、電腦內(nèi)存條和電腦處理器等氓皱。我們來簡單的測試一下:

public class SimpleTest {

    public static void main(String[] args){
        ElectronicFactory factory = new PhoneFactory();
        Screen screen = factory.produceScreen();
        Memory memory = factory.produceMemory();
        Processor processor = factory.produceProcessor();

        System.out.println(screen.getDescription()+"\n"+memory.getDescription()+"\n"+processor.getDescription());

    }
}

控制臺輸出:


image

現(xiàn)在路召,我們可以為不同的電子產(chǎn)品生產(chǎn)工廠設(shè)計一個工廠,即工廠的工廠波材。本例子中股淡,我們創(chuàng)建一個FacotryMaker類,負(fù)責(zé)返回PhoneFactory或者ComputerFactory,客戶端可以通過FactoryMacker工廠來創(chuàng)建所需的工廠廷区,進而生產(chǎn)不同的電子產(chǎn)品部件(屏幕唯灵、處理器、內(nèi)存條)隙轻。
首先定義一個枚舉類型的類FactoryType,用于給FactoryMacker提供選擇參考:

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-4:16
 * @modify by :
 * @info:[工廠類型]
 * @since:
 */
public enum FactoryType {
    PHONE,COMPUTER;
}

然后定義一個生產(chǎn)工廠的工廠類FactoryMacker:

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-4:16
 * @modify by :
 * @info:[工廠創(chuàng)建器:工廠的工廠]
 * @since:
 */
public  class FactoryMacker {

    /**
     * 此工廠方法負(fù)責(zé)創(chuàng)建具體的工廠類
     * @param type
     * @return
     */
    public static ElectronicFactory makeFactory(FactoryType type){
        switch (type){
            case PHONE:
                return new PhoneFactory();
            case COMPUTER:
                return new ComputerFactory();
            default:
                throw new IllegalArgumentException("FactoryType not supported.");
        }
    }
}

最后埠帕,我們定義一個AbstractFactory類來封裝上述的單個工廠類:

package com.ramostear.pattern.abstractfactory;
/**
 * @author ramostear
 * @create-time 2019/1/5 0005-4:21
 * @modify by :
 * @since:
 */
public class AbstractFactory {

    private Screen screen;
    private Memory memory;
    private Processor processor;

    public void createFactory(final ElectronicFactory factory){
        setScreen(factory.produceScreen());
        setMemory(factory.produceMemory());
        setProcessor(factory.produceProcessor());
    }

    public Screen getScreen() {
        return screen;
    }

    private void setScreen(Screen screen) {
        this.screen = screen;
    }

    public Memory getMemory() {
        return memory;
    }

    private void setMemory(Memory memory) {
        this.memory = memory;
    }

    public Processor getProcessor() {
        return processor;
    }

    private void setProcessor(Processor processor) {
        this.processor = processor;
    }
}

現(xiàn)在,整個抽象工廠模式案例已經(jīng)全部實現(xiàn)玖绿。最后測試一下我們創(chuàng)建的抽象工廠模式案例:

package com.ramostear.pattern.abstractfactory;

/**
 * @author ramostear
 * @create-time 2019/1/5 0005-4:27
 * @modify by :
 * @info:[對抽象工廠進行測試]
 * @since:
 */
public class TestAbstractFactory {

    public static void main(String[] args){
        AbstractFactory factory = new AbstractFactory();

        System.out.println("produce phone...");

        factory.createFactory(FactoryMacker.makeFactory(FactoryType.PHONE));
        System.out.println(factory.getScreen().getDescription());
        System.out.println(factory.getMemory().getDescription());
        System.out.println(factory.getProcessor().getDescription());


        System.out.println("produce computer...");

        factory.createFactory(FactoryMacker.makeFactory(FactoryType.COMPUTER));
        System.out.println(factory.getScreen().getDescription());
        System.out.println(factory.getMemory().getDescription());
        System.out.println(factory.getProcessor().getDescription());
    }
}

控制臺輸出:


image

4.適用性

當(dāng)滿足以下場景時適合適用抽象工廠模式

  • 系統(tǒng)應(yīng)該獨立于其產(chǎn)品的創(chuàng)建敛瓷、組成和表示方式
  • 一個系統(tǒng)應(yīng)該配置多個產(chǎn)品系列中的一個
  • 相關(guān)產(chǎn)品對象的系列設(shè)計為一起使用,您需要強制執(zhí)行此約束
  • 您希望提供產(chǎn)品的類庫斑匪,并且只顯示它們的接口呐籽,而不顯示它們的實現(xiàn)
  • 您需要一個運行時值來構(gòu)造一個特定的依賴項
  • 您需要提供一個或多個僅在運行時已知的參數(shù),然后才能解析依賴項

[原文鏈接:https://www.ramostear.com/articles/abstractfactory_design_pattern.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚀瘸,一起剝皮案震驚了整個濱河市狡蝶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贮勃,老刑警劉巖贪惹,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異衙猪,居然都是意外死亡馍乙,警方通過查閱死者的電腦和手機布近,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丝格,“玉大人撑瞧,你說我怎么就攤上這事∠则颍” “怎么了预伺?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長曼尊。 經(jīng)常有香客問我酬诀,道長,這世上最難降的妖魔是什么骆撇? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任瞒御,我火速辦了婚禮,結(jié)果婚禮上神郊,老公的妹妹穿的比我還像新娘肴裙。我一直安慰自己,他們只是感情好涌乳,可當(dāng)我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布蜻懦。 她就那樣靜靜地躺著,像睡著了一般夕晓。 火紅的嫁衣襯著肌膚如雪宛乃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天蒸辆,我揣著相機與錄音征炼,去河邊找鬼。 笑死吁朦,一個胖子當(dāng)著我的面吹牛柒室,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逗宜,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼雄右,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纺讲?” 一聲冷哼從身側(cè)響起擂仍,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎熬甚,沒想到半個月后逢渔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡乡括,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年肃廓,在試婚紗的時候發(fā)現(xiàn)自己被綠了智厌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡盲赊,死狀恐怖铣鹏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哀蘑,我是刑警寧澤诚卸,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站绘迁,受9級特大地震影響合溺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缀台,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一棠赛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧将硝,春花似錦恭朗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽而芥。三九已至律罢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間棍丐,已是汗流浹背误辑。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留歌逢,地道東北人巾钉。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像秘案,于是被迫代替她去往敵國和親砰苍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,925評論 2 344