工廠模式

1. 工廠模式分類

工廠模式主要負(fù)責(zé)將大量有共同接口的類實例化蝗碎,可以動態(tài)的決定創(chuàng)建哪一個類,而不事先知道要實例化具體哪一個類蹭睡。

  • 簡單工廠模式:靜態(tài)工廠模式
  • 工廠模式:多態(tài)工廠模式或者虛擬構(gòu)造工廠模式
  • 抽象工廠模式:又稱為工具箱模式

2. 簡單工廠模式

簡單工廠模式是類的創(chuàng)建模式衍菱,又稱為靜態(tài)工廠方法,是有一個工廠的對象決定創(chuàng)建哪一類具體的產(chǎn)品肩豁。


這里有一個水果類脊串,水果類下面有不同的子類實現(xiàn)
Fruit:

public interface Fruit {
    /**
     * 生長
     */
    void grow();

    /**
     * 收獲
     */
    void harvest();

    /**
     * 種植
     */
    void plant();
}

Apple(其他以此類推,不再一一列出)

public class Apple implements Fruit{
    /**
     * 樹齡
     */
    private int treeAge;

    @Override
    public void grow() {
        log("Apple is growing.");
    }

    @Override
    public void harvest() {
        log("Apple has been harvested.");
    }

    @Override
    public void plant() {
        log("Apple has been planted.");
    }

    public static void log(String msg)
    {
        System.out.println(msg);
    }

    public int getTreeAge(){
        return treeAge;
    }

    public void setTreeAge(int treeAge){
        this.treeAge = treeAge;
    }
}

最后創(chuàng)建一個園丁類清钥,通過傳入不同的水果屬性琼锋,判斷水果的類型進(jìn)行創(chuàng)建,這是典型的靜態(tài)工廠模式祟昭。

public class FruitGardener {
    /**
     * 靜態(tài)工廠方法
     *
     * @param args
     */
    public static void main(String[] args) {
        try{
            Fruit fruit = FruitGardener.factory("apple");
            fruit.harvest();
            fruit = FruitGardener.factory("grape");
            fruit.harvest();
            fruit = FruitGardener.factory("strawberry");
            fruit.harvest();
        }catch (BadFruitException e){
            e.printStackTrace();
        }
    }


    public static Fruit factory(String fruit) throws BadFruitException {
        switch (fruit) {
            case "apple":
                return new Apple();
            case "strawberry":
                return new Strawberry();
            case "grape":
                return new Grape();
            default:
                throw new BadFruitException("Bad fruit request");
        }
    }

}

總結(jié)一下缕坎,簡單工廠模式的結(jié)構(gòu)為:


3. 工廠模式

工廠模式又成為動態(tài)工廠模式,由于靜態(tài)工廠模式的缺點(diǎn)是篡悟,有新的類加入時需要修改工廠類代碼谜叹,不符合開閉原則,因此引入類動態(tài)工廠模式搬葬,使用多態(tài)的方式去創(chuàng)建荷腊,具體創(chuàng)建類的過程交給子類去做,工廠和產(chǎn)品之間是一種平級的等級結(jié)構(gòu)急凰。



工廠模式存在四個角色:抽象產(chǎn)品女仰、具體產(chǎn)品、構(gòu)造者抡锈、具體構(gòu)造者
這里采用一個簡單的例子去說明
抽象產(chǎn)品類:PenCore 鋼筆:顏色+書寫

public abstract class PenCore {

    public String color;

    public abstract void writeWord(String s);

}

具體產(chǎn)品類:黑色鋼筆:設(shè)置顏色+書寫文字

public class BlackPenCore extends PenCore{

    public BlackPenCore(){
        color = "black";
    }

    @Override
    public void writeWord(String s) {
        System.out.println("write with "+ color+ ": "+s);
    }
}

構(gòu)造者:BallPen: 返回一個鋼筆對象

public abstract class BallPen {
    BallPen(){
        System.out.println("create the pen with the "+ getPenCore().color+".");
    }

    public abstract PenCore getPenCore();
}

具體構(gòu)造者:BlackBallPen:返回具體的鋼筆對象

public class BlackBallPen extends BallPen{

    @Override
    public PenCore getPenCore(){
        return new BlackPenCore();
    }
}

模式的具體使用

public class Application {
    public static void main(String[] args) {
        PenCore penCore;
        BallPen ballPen = new BlueBallPen();
        penCore = ballPen.getPenCore();
        penCore.writeWord("你好");

        ballPen = new RedBallPen();
        penCore = ballPen.getPenCore();
        penCore.writeWord("Hello");

        ballPen = new BlackBallPen();
        penCore = ballPen.getPenCore();
        penCore.writeWord("ni hao!");
    }
}

運(yùn)行結(jié)果:

create the pen with the blue.
write with blue: 你好
create the pen with the red.
write with red: Hello
create the pen with the black.
write with black: ni hao!

其實Java的集合框架也有采用這種設(shè)計模式:


綜上所述疾忍,工廠模式的結(jié)構(gòu)為:


4. 抽象工廠模式

抽象工廠模式是工廠模式中最具一般性的一種形態(tài),提供一個創(chuàng)建一系列或相互依賴對象的接口床三,而無須制定他們具體的類一罩。
它與工廠模式的最大區(qū)別是:工廠模式面對一個產(chǎn)品等級的結(jié)構(gòu),而抽象工廠模式面對多個產(chǎn)品等級結(jié)構(gòu)撇簿。



舉個例子擒抛,兩個抽象產(chǎn)品一個褲子一個上衣:
褲子抽象產(chǎn)品:

public interface Trousers {
    int getWaistSize();
    int getHeight();
    String getName();
}

上衣抽象產(chǎn)品

public interface UpperClothes {
    int getChestSize();
    int getHeight();
    String getName();
}

褲子分為西褲和牛仔褲推汽,這里只顯示西褲:

public class WesternTrousers implements Trousers{

    private int waistSize;

    private int height;

    private String name;

    public WesternTrousers(int waistSize, int height, String name) {
        this.waistSize = waistSize;
        this.height = height;
        this.name = name;
    }

    @Override
    public int getWaistSize() {
        return waistSize;
    }

    @Override
    public int getHeight() {
        return height;
    }

    @Override
    public String getName() {
        return name;
    }
}

上衣分為牛仔上衣和西裝,這里只寫西裝

public class WesternUpperClothes implements UpperClothes {

   private int chestSize;

   private int height;

   private String name;

   public WesternUpperClothes(int chestSize, int height, String name) {
       this.chestSize = chestSize;
       this.height = height;
       this.name = name;
   }

   @Override
   public int getChestSize() {
       return chestSize;
   }

   @Override
   public int getHeight() {
       return height;
   }

   @Override
   public String getName() {
       return name;
   }
}

此時創(chuàng)建抽象工廠歧沪,具有創(chuàng)建上衣和褲子的方法

public interface ClothesFactory {
    UpperClothes createUpperClothes(int chestSize, int height);
    Trousers createTrousers(int waitSize, int height);
}

具體工廠包括兩個歹撒,北京的西裝工廠和上海的牛仔工廠,這里列舉北京的西裝工廠

public class BeijingClothesFactory implements ClothesFactory{
    @Override
    public UpperClothes createUpperClothes(int chestSize, int height) {
        return new WesternUpperClothes(chestSize, height, "北京牌西服上衣");
    }

    @Override
    public Trousers createTrousers(int waitSize, int height) {
        return new WesternTrousers(waitSize, height, "北京牌西服褲子");
    }
}

最后設(shè)置服裝店诊胞,輸入人的信息暖夭,可以創(chuàng)建具體的服裝

public class Shop {
    UpperClothes clothes;
    Trousers trousers;
    public void giveSuit(ClothesFactory factory, int chestSize, int waistSize, int height){
        clothes = factory.createUpperClothes(chestSize, height);
        trousers = factory.createTrousers(waistSize, height);
        showMess();
    }

    private void showMess(){
        System.out.println("<套裝信息>");
        System.out.println(clothes.getName()+" ");
        System.out.println("胸圍:"+ clothes.getChestSize());
        System.out.println("身高:"+ clothes.getHeight());

        System.out.println(trousers.getName()+" ");
        System.out.println("腰圍:"+ trousers.getWaistSize());
        System.out.println("身高:"+ trousers.getHeight());
    }
}

最后,服裝店可以對衣服進(jìn)行定制

public class Application {
    public static void main(String[] args) {
        Shop shop = new Shop();
        ClothesFactory factory = new BeijingClothesFactory();
        shop.giveSuit(factory, 110, 82, 170);
        factory = new ShanghaiClothesFactory();
        shop.giveSuit(factory, 120, 88, 180);
    }
}

打印結(jié)果如下:

<套裝信息>
北京牌西服上衣 
胸圍:110
身高:170
北京牌西服褲子 
腰圍:82
身高:170

總結(jié)抽象工廠的模式為:


因此抽象工廠模式適用于以下情況:

  1. 一個系統(tǒng)不應(yīng)當(dāng)依賴與產(chǎn)品類實力如何被創(chuàng)建撵孤、組合和表達(dá)的細(xì)節(jié)迈着;
  2. 這個系統(tǒng)中有多于一個的產(chǎn)品族,而系統(tǒng)只消費(fèi)其中某一族的產(chǎn)品邪码;
  3. 同屬于一個產(chǎn)品族的產(chǎn)品是一起使用的裕菠;
  4. 系統(tǒng)提供一個產(chǎn)品類的庫,所有產(chǎn)品以同樣的接口出現(xiàn)闭专,從而實現(xiàn)客戶端不依賴于實現(xiàn)奴潘。

5. 源碼參考

由于篇幅原因,只顯示了一個子類影钉,完整的系統(tǒng)調(diào)用請參考鏈接画髓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市平委,隨后出現(xiàn)的幾起案子奈虾,更是在濱河造成了極大的恐慌,老刑警劉巖廉赔,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肉微,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜡塌,警方通過查閱死者的電腦和手機(jī)碉纳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岗照,“玉大人村象,你說我怎么就攤上這事笆环≡苤粒” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵躁劣,是天一觀的道長迫吐。 經(jīng)常有香客問我,道長账忘,這世上最難降的妖魔是什么志膀? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任熙宇,我火速辦了婚禮,結(jié)果婚禮上溉浙,老公的妹妹穿的比我還像新娘烫止。我一直安慰自己,他們只是感情好戳稽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布馆蠕。 她就那樣靜靜地躺著,像睡著了一般惊奇。 火紅的嫁衣襯著肌膚如雪互躬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天颂郎,我揣著相機(jī)與錄音吼渡,去河邊找鬼。 笑死乓序,一個胖子當(dāng)著我的面吹牛寺酪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播竭缝,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼房维,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了抬纸?” 一聲冷哼從身側(cè)響起咙俩,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎湿故,沒想到半個月后阿趁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坛猪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年脖阵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片墅茉。...
    茶點(diǎn)故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡命黔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出就斤,到底是詐尸還是另有隱情悍募,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布洋机,位于F島的核電站坠宴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏绷旗。R本人自食惡果不足惜喜鼓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一副砍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧庄岖,春花似錦豁翎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至硼控,卻和暖如春刘陶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牢撼。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工匙隔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人熏版。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓纷责,卻偏偏與公主長得像,于是被迫代替她去往敵國和親撼短。 傳聞我的和親對象是個殘疾皇子再膳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評論 2 354

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

  • 工廠模式是我們最常用的實例化對象模式了,是用工廠方法代替new操作的一種模式曲横。通常我們所說的工廠模式是指工廠方法模...
    zfylin閱讀 1,313評論 0 7
  • 工廠模式概述 意義 問題引出在面向?qū)ο缶幊讨? 最通常的方法是一個new操作符產(chǎn)生一個對象實例,new操作符就是用...
    stoneyang94閱讀 491評論 0 0
  • 三月九日喂柒,我與夏爾途經(jīng)金州,行至漢江大橋禾嫉,在江南岸邊見到有依江而建供路人休憩的公園灾杰,遂停駐歇息。驚蟄剛過二日熙参,巴陽...
    安卓氣體滅火閱讀 734評論 0 5
  • 周日艳吠,蜜蜜與您一起分享瑜伽[玫瑰][玫瑰] 脾經(jīng) 脾主運(yùn)化,幫助胃腸吸收有助于吸收營養(yǎng)孽椰,生血昭娩。 脾經(jīng)運(yùn)化...
    王蘭_hope閱讀 128評論 0 0
  • 上圖形象化地說明了閱讀的好處栏渺,然而膀捷,怎樣構(gòu)建你自己的閱讀清單呢全庸? 下面提供四種方法,無論你是否經(jīng)常讀書壶笼,都可以使用...
    安曉輝0閱讀 1,576評論 0 35