工廠模式

簡單工廠模式

由一個工廠對象決定創(chuàng)建出哪一種產(chǎn)品類的實例计寇。屬于創(chuàng)建型模式常拓,但不屬于GoF(23種設(shè)計模式)。

舉例:首先建立一個接口類毛秘,名為Animal,并在其中定義一個name()方法。

public interface Animal {
    public void name();
}

分別建立Cat叫挟、Dog艰匙、Bird實體類并實現(xiàn)Animal

public class Cat implements Animal{
    public void name() {
        System.out.println("A cat");
    }
}

public class Dog implements Animal {
    public void name() {
        System.out.println("A dog");
    }
}

public class Dog implements Animal {
    public void name() {
        System.out.println("A dog");
    }
}

建立工廠類抹恳,名為AnimalFactory员凝,定義create()方法,傳入?yún)?shù)為想要創(chuàng)建對象的實體類

public class AnimalFactory {
    public Animal create(Class clazz) {
        if (clazz != null) {
            try {
                return (Animal) clazz.getDeclaredConstructor().newInstance(); //Java 9 以后不推薦直接使用clazz.newInstance()創(chuàng)建對象
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

這樣一個簡單工廠模式的樣例就成型了奋献,我們來新建一個測試類健霹,測試AnimalFactory工廠類能創(chuàng)建出我們指定的對象。

public class AnimalFactoryTest {
    public static void main(String[] args) {
        AnimalFactory factory = new AnimalFactory();
        Animal animal = factory.create(Cat.class);
        animal.name();
    }
}

輸出結(jié)果如下所示:

A cat

優(yōu)點:簡單工廠模式用戶只需要傳入正確的參數(shù)就可以獲取所需要的對象瓶蚂,無須知道它的創(chuàng)建細節(jié)糖埋。
缺點:工廠類的職責(zé)過于沉重,當添加新產(chǎn)品的時候窃这,需要修改工廠類的判斷邏輯瞳别,違反了開閉原則。不利于擴展過于復(fù)雜的產(chǎn)品結(jié)構(gòu)杭攻。

總結(jié):簡單工廠模式的適用場景有限祟敛,只適用于創(chuàng)建對象數(shù)量比較少,創(chuàng)建邏輯不復(fù)雜而且過程比較穩(wěn)定的場景兆解。

工廠方法模式

定義一個創(chuàng)建產(chǎn)品對象的工廠接口馆铁,讓實現(xiàn)這一個接口的工廠類來決定實例化哪種產(chǎn)品對象,將類的實例化工作推遲到子類中完成锅睛。屬于創(chuàng)建型模式埠巨,屬于GoF。其核心結(jié)構(gòu)有四個角色:抽象工廠衣撬、具體工廠乖订、抽象產(chǎn)品、具體產(chǎn)品具练。

舉例:抽象產(chǎn)品和具體產(chǎn)品我們依舊使用上面所建立的Animal乍构、CatDogBird扛点。
接下來我們來建立抽象工廠類哥遮,名為IAnimalFactory,它提供一個名為create()的方法

public interface IAnimalFactory {
    Animal create();
}

分別建立CatFactory陵究、DogFactory眠饮、BirdFactory實現(xiàn)抽象工廠類IAnimalFactory

public class CatFactory implements IAnimalFactory {
    public Animal create() {
        return new Cat();
    }
}

public class DogFactory implements IAnimalFactory {
    public Animal create() {
        return new Dog();
    }
}

public class BirdFactory implements IAnimalFactory {
    public Animal create() {
        return new Bird();
    }
}

建立測試類AnimalFactoryTest來進行測試

public class AnimalFactoryTest {
    public static void main(String[] args) {
        IAnimalFactory factory = new CatFactory();
        Animal animal = factory.create();
        animal.name();
    }
}

輸出結(jié)果如下所示:

A cat

優(yōu)點:用戶只需關(guān)心所需產(chǎn)品對應(yīng)的工廠,無需關(guān)心創(chuàng)建細節(jié)铜邮。加入新產(chǎn)品符合開閉原則仪召,提高了系統(tǒng)的可擴展性寨蹋。
缺點:類的個數(shù)容易過多,增加了代碼結(jié)構(gòu)的復(fù)雜度扔茅。增加了系統(tǒng)的抽象性和理解難度已旧。

總結(jié):工廠方法模式是簡單工廠模式的衍生,解決了許多簡單工廠模式的問題,完全實現(xiàn)開閉原則召娜,易于擴展运褪。

工廠方法經(jīng)常用在以下兩種情況中:
第一種情況是對于某個產(chǎn)品,調(diào)用者清楚地知道應(yīng)該使用哪個具體工廠服務(wù)玖瘸,實例化該具體工廠秸讹,生產(chǎn)出具體的產(chǎn)品來。Java Collection中的iterator() 方法即屬于這種情況雅倒。
第二種情況璃诀,只是需要一種產(chǎn)品,而不想知道也不需要知道究竟是哪個工廠為生產(chǎn)的文虏,即最終選用哪個具體工廠的決定權(quán)在生產(chǎn)者一方,它們根據(jù)當前系統(tǒng)的情況來實例化一個具體的工廠返回給使用者殖演,而這個決策過程這對于使用者來說是透明的年鸳。

抽象工廠模式

隸屬于設(shè)計模式中的創(chuàng)建型模式,用于產(chǎn)品族的構(gòu)建搔确。提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,無需指定他們具體的類膳算。

首先我們先來了解一下產(chǎn)品族和產(chǎn)品等級結(jié)構(gòu),如下圖所示涕蜂,方塊、圓机隙、三角各代表一種產(chǎn)品蜘拉,不同的顏色對應(yīng)不同的型號(也可理解為品牌)。同一品牌下的不同產(chǎn)品構(gòu)成一個產(chǎn)品族有鹿,同種產(chǎn)品的不同品牌構(gòu)成一個產(chǎn)品等級結(jié)構(gòu)旭旭。


我們來看一個例子骤肛,手機斑鼻、平板和筆記本這三種對象,我們可以把他們看成是一個產(chǎn)品族稳吮,針對于這一個產(chǎn)品族我們會有很多的品牌,比如蘋果稍味、華為和聯(lián)想咸产,他們?nèi)齻€針對于每一項產(chǎn)品又組成一個產(chǎn)品等級結(jié)構(gòu)。
我們就可以通過抽象工廠方法模式來構(gòu)建這樣一個工廠仲闽。

我問先根據(jù)產(chǎn)品建立對應(yīng)的抽象產(chǎn)品類脑溢,分別為PhonePadLaptop,這里只簡單的添加了一個name方法

public interface Phone {
    void name();
}

public interface Phone {
    void name();
}

public interface Laptop {
    void name();
}

然后我們建立一個頂層的抽象工廠類赖欣,名為BeanFactory,在其中定義三個方法屑彻,分別用來創(chuàng)建手機、平板和筆記本對象顶吮。

public interface BeanFactory {
    //生成手機
    Phone createPhone();
    //生成平板
    Pad createPad();
    //生成筆記本
    Laptop createLaptop();
}

這時我們需要創(chuàng)建產(chǎn)品的具體實現(xiàn)類社牲,這里以蘋果產(chǎn)品為例,需要分別對Phone悴了、Pad和Laptop進行實現(xiàn)搏恤,這里編寫了IPhone、IPad和MacBook三個類

public class IPhone implements Phone {
    public void name() {
        System.out.println("IPhone");
    }
}

public class IPad implements Pad {
    public void name() {
        System.out.println("IPad");
    }
}

public class MacBook implements Laptop {
    public void name() {
        System.out.println("MacBook");
    }
}

然后我們來編寫蘋果工廠的具體實現(xiàn)類湃交,名為AppleFactory熟空,來實現(xiàn)BeanFactory

public class AppleFactory implements BeanFactory {
    public Phone createPhone() {
        return new IPhone();
    }

    public Pad createPad() {
        return new IPad();
    }

    public Laptop createLaptop() {
        return new MacBook();
    }
}

我們來測試以下工廠是否可以正常工作,編寫測試類BeanFactoryTest

public class BeanFactoryTest {
    public static void main(String[] args) {
        BeanFactory factory = new AppleFactory();
        factory.createPhone().name();
        factory.createPad().name();
        factory.createLaptop().name();
    }
}

輸出為:

IPhone
IPad
MacBook

這個過程中我們發(fā)現(xiàn)抽象工廠模式是對擴展開放的搞莺,但是如果新添加一種產(chǎn)品息罗,勢必要修改頂層的抽象工廠類,沒有做到對修改關(guān)閉才沧,也就違反了開閉原則迈喉。

適用場景:
1.客戶端(應(yīng)用層)不關(guān)注產(chǎn)品類實例如何被實現(xiàn)、創(chuàng)建的細節(jié)温圆。
2.一系列相關(guān)的產(chǎn)品對象(同一產(chǎn)品族)一起使用創(chuàng)建對象時需要大量重復(fù)的代碼
3.提供一個已經(jīng)確定產(chǎn)品類的庫挨摸,所有的產(chǎn)品以同樣的接口出現(xiàn),使得客戶端不依賴于具體實現(xiàn)

優(yōu)點:具體產(chǎn)品的實現(xiàn)代碼被隔離岁歉,使得調(diào)用者無需關(guān)心創(chuàng)建細節(jié)得运。將一個系列的產(chǎn)品族統(tǒng)一到一起進行創(chuàng)建。
缺點:規(guī)定了所有可能被創(chuàng)建的產(chǎn)品的集合刨裆,產(chǎn)品族中擴展新的產(chǎn)品變得困難澈圈,需要修改抽象工廠中的接口。增加了系統(tǒng)的抽象性和理解難度帆啃。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市努潘,隨后出現(xiàn)的幾起案子坤学,更是在濱河造成了極大的恐慌报慕,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件飞苇,死亡現(xiàn)場離奇詭異布卡,居然都是意外死亡雇盖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門贸街,熙熙樓的掌柜王于貴愁眉苦臉地迎上來薛匪,“玉大人卷哩,你說我怎么就攤上這事。” “怎么了渐白?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長栋齿。 經(jīng)常有香客問我襟诸,道長,這世上最難降的妖魔是什么菇用? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任惋鸥,我火速辦了婚禮,結(jié)果婚禮上卦绣,老公的妹妹穿的比我還像新娘。我一直安慰自己廊蜒,他們只是感情好溅漾,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布樟凄。 她就那樣靜靜地躺著,像睡著了一般汰现。 火紅的嫁衣襯著肌膚如雪叔壤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天嗅战,我揣著相機與錄音驮捍,去河邊找鬼脚曾。 笑死,一個胖子當著我的面吹牛本讥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播色查,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼秧了,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了示惊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钧汹,失蹤者是張志新(化名)和其女友劉穎录择,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體塘秦,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡尊剔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年须误,在試婚紗的時候發(fā)現(xiàn)自己被綠了仇轻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡篷店,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出方淤,到底是詐尸還是另有隱情蹄殃,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站按厘,受9級特大地震影響钱慢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜束莫,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望策严。 院中可真熱鬧,春花似錦逛绵、人聲如沸倔韭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽醇疼。三九已至,卻和暖如春鲤孵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辰如。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工琉兜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人豌蟋。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓梧疲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親幌氮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 工廠模式是我們最常用的實例化對象模式了米者,是用工廠方法代替new操作的一種模式。通常我們所說的工廠模式是指工廠方法模...
    zfylin閱讀 1,314評論 0 7
  • 工廠方法模式通過引入工廠等級結(jié)構(gòu)胰丁,解決了簡單工廠模式中工廠類職責(zé)太重的問題锦庸,但由于工廠方法模式中的每個工廠只生產(chǎn)一...
    justCode_閱讀 1,198評論 1 6
  • 設(shè)計原則: 要依賴抽象酸员,不要依賴具體類 目錄 本文的結(jié)構(gòu)如下: 什么是抽象工廠模式 為什么要用該模式 模式的結(jié)構(gòu) ...
    w1992wishes閱讀 1,116評論 0 6
  • 巴圖吉雅拿起一盞銅燈盞讳嘱,上面沾滿了紅色的銹蝕斑塊,多少年以前了這是沥潭?那時,父親還和一頭馬駒子一樣年輕汇恤,祖父的身體也...
    勒尤閱讀 431評論 0 0
  • 第四套人民幣已經(jīng)在市場上流通超過30年匠璧,2018年5月1日,這套人民幣部分券別退出流通夷恍,而本月30日將結(jié)束集中兌換...
    思其自然閱讀 274評論 0 1