Java 設計模式——工廠模式

image

前言

最近在復習java設計模式中的工廠模式痰催。本來有一點小小的理解兜辞。感覺都寫的不錯,就是有點太零散了夸溶,最后還是決定自己手寫一把逸吵,加深印象。順便做個總結(jié)缝裁,以后復習起來也方便許多扫皱。

一、簡介

目前從網(wǎng)上了解工廠模式大體分為簡單工廠捷绑、工廠方法韩脑、抽象工廠等三種模式。工廠方法模式也可稱為工廠模式粹污,與抽象模式都是屬于GOF23種設計模式中的一員段多。可以大概理解為:簡單工廠進階變成了工廠方法壮吩,然后再進階成了抽象工廠进苍。難度逐步增加,也越來越抽象鸭叙。下面按先易到難逐個分析琅捏。

二、簡單工廠模式

屬于創(chuàng)建型模式递雀,又叫做靜態(tài)工廠方法模式,不屬于23種GOF設計模式之一蚀浆。是由一個工廠對象決定創(chuàng)建出哪一種產(chǎn)品類的實例缀程。實質(zhì)是由一個工廠類根據(jù)傳入的參數(shù),動態(tài)決定應該創(chuàng)建哪一個產(chǎn)品類(這些產(chǎn)品類繼承自一個父類或接口)的實例市俊。

作用:將“類實例化的操作”與“使用對象的操作”分開杨凑,讓使用者不用知道具體參數(shù)就可以實例化出所需要的“產(chǎn)品”類,從而避免了在客戶端代碼中顯式指定摆昧,實現(xiàn)了解耦撩满。

主要角色
工廠:負責實現(xiàn)創(chuàng)建所有實例的內(nèi)部邏輯,并提供一個外界調(diào)用的方法,創(chuàng)建所需的產(chǎn)品對象伺帘。
抽象產(chǎn)品:負責描述產(chǎn)品的公共接口
具體產(chǎn)品:描述生產(chǎn)的具體產(chǎn)品昭躺。
舉個簡單易懂的例子:
“假設”有一臺飲料機(工廠),可以調(diào)出各種口味的飲料(抽象產(chǎn)品)伪嫁,有三個按鈕(參數(shù))對應這三種飲料(具體產(chǎn)品)领炫。這時候你可以根據(jù)點擊按鈕來選擇你喜歡的飲料。

/**
 *  @ Product.java
 *  抽象產(chǎn)品
 *  描述產(chǎn)品的公共接口
 */
abstract  class Product {
    //產(chǎn)品介紹
    abstract void intro();
}

/**
 * @ AProduct.java
 * 具體產(chǎn)品A
 * (可以看成是一種飲料:可樂)
 */
public class AProduct extends Product{
    @Override
    void intro() {
        System.out.println("可樂");
    }
}

/**
 * @ BProduct.java
 * @具體產(chǎn)品B
 * @(可以看成是一種飲料:奶茶)
 */
public class BProduct extends Product{
    @Override
    void intro() {
        System.out.println("奶茶");
    }
}

/**
 * @ CProduct.java
 * 具體產(chǎn)品C
 * (可以看成是一種飲料:咖啡)
 */
public class CProduct extends Product{
    @Override
    void intro() {
        System.out.println("咖啡");
    }
}
image.gif

Factory.java

/**
 * 工廠
 * 負責實現(xiàn)創(chuàng)建所有實例的內(nèi)部邏輯张咳,并提供一個外界調(diào)用的方法帝洪,創(chuàng)建所需的產(chǎn)品對象。
 */
public class Factory {
    /**
     * 供外界調(diào)用的方法
     * (可以看成是對外提供的三種按鈕)
     * @param type 
     * @return 產(chǎn)品實例
     */
    public static Product getProduct(String type) {
        switch (type) {
            case "A":
                return new AProduct();
            case "B":
                return new BProduct();
            case "C":
                return new CProduct();
            default:
                return null;
        }
    }
}
image.gif

測試

public class Test {
    public static void main(String[] args) {
        //創(chuàng)建具體的工廠
        Factory factory = new Factory();
        //根據(jù)傳入的參數(shù)生產(chǎn)不同的產(chǎn)品實例
        //(按下不同的按鈕脚猾,獲取飲料)
        Product A = Factory.getProduct("A");
        A.intro();
        Product B = Factory.getProduct("B");
        B.intro();
        Product C = Factory.getProduct("C");
        C.intro();
    }
}
image.gif
image

根據(jù)例子可以描述為:一個抽象產(chǎn)品類葱峡,可以派生出多個具體產(chǎn)品類。一個具體工廠類龙助,通過往此工廠的static方法中傳入不同參數(shù)砰奕,產(chǎn)出不同的具體產(chǎn)品類實例。

優(yōu)點:將創(chuàng)建使用工作分開泌参,不必關(guān)心類對象如何創(chuàng)建脆淹,實現(xiàn)了解耦;
缺點:違背“開放 - 關(guān)閉原則”沽一,一旦添加新產(chǎn)品就不得不修改工廠類的邏輯盖溺,這樣就會造成工廠邏輯過于復雜。

三铣缠、工廠方法模式

又稱工廠模式烘嘱、多態(tài)工廠模式虛擬構(gòu)造器模式,通過定義工廠父類負責定義創(chuàng)建對象的公共接口蝗蛙,而子類則負責生成具體的對象蝇庭。一種常用的對象創(chuàng)建型設計模式,此模式的核心精神是封裝 類中不變的部分。

作用:將類的實例化(具體產(chǎn)品的創(chuàng)建)延遲到工廠類的子類(具體工廠)中完成捡硅,即由子類來決定應該實例化(創(chuàng)建)哪一個類哮内。

主要角色
抽象工廠:描述具體工廠的公共接口
具體工廠:描述具體工廠,創(chuàng)建產(chǎn)品的實例壮韭,供外界調(diào)用
抽象產(chǎn)品:負責描述產(chǎn)品的公共接口
具體產(chǎn)品:描述生產(chǎn)的具體產(chǎn)品

舉個簡單易懂的例子:
“假設”有各類的飲料機(抽象工廠)北发,可以調(diào)出各種的飲料(抽象產(chǎn)品)。但是一類飲料機(具體工廠)喷屋,只能生產(chǎn)一種飲料(具體產(chǎn)品)琳拨。如果你需要喝可樂,就需要買可樂飲料機屯曹。

產(chǎn)品:Product.java 狱庇、ProductA.java 惊畏、ProductB.java

/**
 * @ Product.java 
 *   抽象產(chǎn)品
 */
abstract class Product {
    //產(chǎn)品介紹
    abstract void intro();
}

/**
 * @ ProductA.java 
 * 具體產(chǎn)品A
 */
public class ProductA extends Product{
    @Override
    void intro() {
        System.out.println("飲料A");
    }
}

/**
 * @ ProductB.java 
 * 具體產(chǎn)品B
 */
public class ProductB extends Product{
    @Override
    void intro() {
        System.out.println("飲料B");
    }
}
image.gif

工廠:Factory.java、FactoryA.java 密任、FactoryB.java

/**
 *  @ Factory.java
 *    抽象工廠
 */
abstract class Factory {
    //生產(chǎn)產(chǎn)品
    abstract Product getProduct();
}

/**
 * @ FactoryA.java
 * 具體工廠A
 * 負責具體的產(chǎn)品A生產(chǎn)
 */
public class FactoryA extends Factory{
    @Override
    Product getProduct() {
        return new ProductA();
    }
}

/**
 * @ FactoryB.java
 * @具體工廠B
 * 負責具體的產(chǎn)品B生產(chǎn)
 */
public class FactoryB extends Factory{
    @Override
    Product getProduct() {
        return new ProductB();
    }
}
image.gif

測試:Test.java

public class Test {
    public static void main(String[] args) {
        //創(chuàng)建具體的工廠
        FactoryA factoryA = new FactoryA();
        //生產(chǎn)相對應的產(chǎn)品
        factoryA.getProduct().intro();
        FactoryB factoryB = new FactoryB();
        factoryB.getProduct().intro();
    }
}
image.gif

根據(jù)例子可以描述為:一個抽象產(chǎn)品類颜启,可以派生出多個具體產(chǎn)品類。一個抽象工廠類批什,可以派生出多個具體工廠類农曲。每個具體工廠類只能創(chuàng)建一個具體產(chǎn)品類的實例

優(yōu)點:

  1. 符合開-閉原則:新增一種產(chǎn)品時驻债,只需要增加相應的具體產(chǎn)品類和相應的工廠子類即可
  2. 符合單一職責原則:每個具體工廠類只負責創(chuàng)建對應的產(chǎn)品

缺點:

  1. 增加了系統(tǒng)的復雜度:類的個數(shù)將成對增加
  2. 增加了系統(tǒng)的抽象性和理解難度
  3. 一個具體工廠只能創(chuàng)建一種具體產(chǎn)品

四乳规、抽象工廠模式

定義:提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無須指定它們具體的類合呐;具體的工廠負責實現(xiàn)具體的產(chǎn)品實例暮的。
解決的問題:每個工廠只能創(chuàng)建一類產(chǎn)品(工廠方法模式)

抽象工廠模式與工廠方法模式最大的區(qū)別:抽象工廠中每個工廠可以創(chuàng)建多種類的產(chǎn)品;而工廠方法每個工廠只能創(chuàng)建一類

主要對象
抽象工廠:描述具體工廠的公共接口
具體工廠:描述具體工廠淌实,創(chuàng)建產(chǎn)品的實例冻辩,供外界調(diào)用
抽象產(chǎn)品族:描述抽象產(chǎn)品的公共接口
抽象產(chǎn)品:描述具體產(chǎn)品的公共接口
具體產(chǎn)品:具體產(chǎn)品

舉個簡單易懂的例子:(找了個不怎么好的比喻,看不懂得可以看相關(guān)推薦鏈接)
“假設”有各類的自動售賣機(抽象工廠)拆祈,可以出售各類食品(抽象產(chǎn)品族)恨闪。
有飲料、零食(抽象產(chǎn)品)放坏,比如常見的零食售賣機(具體工廠)咙咽,出售礦泉水與面包(具體產(chǎn)品)。

產(chǎn)品:Product淤年、ProductA钧敞、ProductB、ProductAa麸粮、ProductBb

/**
 * @ Product.java
 * 抽象產(chǎn)品族 (食品)
 */
abstract class Product {
    //產(chǎn)品介紹
    abstract void intro();
}

/**
 * @ ProductA.java
 * 抽象產(chǎn)品  (飲料)
 */
abstract class ProductA extends Product{
    @Override
    abstract void intro();
}

/**
 * @ ProductB.java
 * 抽象產(chǎn)品  (零食)
 */
abstract class ProductB extends Product{
    @Override
    abstract void intro();
}

/**
 * @ ProductAa.java
 * 具體產(chǎn)品  (礦泉水)
 */
public  class ProductAa extends ProductA{
    @Override
    void intro() {
        System.out.println("礦泉水");
    }
}

/**
 * @ ProductBb.java
 * 抽象產(chǎn)品  (面包)
 */
public class ProductBb extends ProductB{
    @Override
    void intro() {
        System.out.println("面包");
    }
}
image.gif

工廠:Factory.java溉苛、FactoryA.java

/**
 * @ Factory.java
 * 抽象工廠
 */
abstract class Factory {
    //生產(chǎn)飲料
    abstract Product getProductA();
    //生產(chǎn)零食
    abstract Product getProductB();
}

/**
 * @ FactoryA.java
 * 具體工廠A
 * 負責具體的A類產(chǎn)品生產(chǎn)
 */
public class FactoryA extends Factory{
    @Override
    Product getProductA() {
        //生產(chǎn)礦泉水
        return new ProductAa();
    }
    @Override
    Product getProductB() {
        //生產(chǎn)面包
        return new ProductBb();
    }
}

image.gif

測試:Test.java

public class Test {
    public static void main(String[] args) {
        //創(chuàng)建零食售賣機(具體工廠),
        FactoryA factoryA = new FactoryA();
        //獲取礦泉水與面包(具體產(chǎn)品)
        factoryA.getProductA().intro();
        factoryA.getProductB().intro();
    }
}
image.gif
image
image.gif

?

根據(jù)實例可以描述為: 多個抽象產(chǎn)品類弄诲,每個抽象產(chǎn)品類可以派生出多個具體產(chǎn)品類愚战。一個抽象工廠類,可以派生出多個具體工廠類齐遵。 每個具體工廠類可以創(chuàng)建多個具體產(chǎn)品類的實例凤巨。.

優(yōu)點:

  1. 降低耦合
  2. 符合開-閉原則
  3. 符合單一職責原則
  4. 不使用靜態(tài)工廠方法,可以形成基于繼承的等級結(jié)構(gòu)洛搀。

缺點:難以擴展新種類產(chǎn)品

五、總結(jié)

角色不同:

  1. 簡單工廠:具體工廠佑淀、抽象產(chǎn)品留美、具體產(chǎn)品
  2. 工廠方法:抽象工廠、具體工廠、抽象產(chǎn)品谎砾、具體產(chǎn)品
  3. 抽象工廠:抽象工廠逢倍、具體工廠、抽象產(chǎn)品族景图、抽象產(chǎn)品较雕、具體產(chǎn)品

定義:

  1. 簡單工廠:由一個工廠類根據(jù)傳入的參數(shù),動態(tài)決定應該創(chuàng)建哪一個產(chǎn)品類(繼承自一個父類或接口)的實例挚币。
  2. 工廠方法:定義工廠父類負責定義創(chuàng)建對象的公共接口亮蒋,而子類則負責生成具體的對象
  3. 抽象工廠:提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無須指定它們具體的類妆毕;具體的工廠負責實現(xiàn)具體的產(chǎn)品實例慎玖。

對比:

  1. 工廠方法模式解決了簡單工廠模式的“開放 - 關(guān)閉原則
  2. 抽象工廠模式解決了工廠方法模式一個具體工廠只能創(chuàng)建一類產(chǎn)品

六、Demo地址

https://github.com/DayorNight/DesignPattern

六笛粘、參考文檔

簡單工廠模式

http://www.reibang.com/p/e55fbddc071c

https://baike.baidu.com/item/%E7%AE%80%E5%8D%95%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/8801727

工廠方法模式

http://www.reibang.com/p/d0c444275827

抽象工廠模式

http://www.reibang.com/p/7deb64f902db

七趁怔、內(nèi)容推薦

CSDN: https://blog.csdn.net/cs_lwb/article/details/83999073

上一篇《JAVA 設計模式——單例模式》

如果你覺得我寫的不錯或者對您有所幫助的話。不妨頂一個(點個贊唄)薪前,也方便以后復習

您的每個舉動都是對我莫大的支持

謝謝了H笈!示括!

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铺浇,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子例诀,更是在濱河造成了極大的恐慌随抠,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件繁涂,死亡現(xiàn)場離奇詭異拱她,居然都是意外死亡,警方通過查閱死者的電腦和手機扔罪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門秉沼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人矿酵,你說我怎么就攤上這事唬复。” “怎么了全肮?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵敞咧,是天一觀的道長嗽元。 經(jīng)常有香客問我贯底,道長番电,這世上最難降的妖魔是什么聚谁? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮测砂,結(jié)果婚禮上茵烈,老公的妹妹穿的比我還像新娘。我一直安慰自己砌些,他們只是感情好呜投,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著存璃,像睡著了一般仑荐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上有巧,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天释漆,我揣著相機與錄音,去河邊找鬼篮迎。 笑死男图,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的甜橱。 我是一名探鬼主播逊笆,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼岂傲!你這毒婦竟也來了难裆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤镊掖,失蹤者是張志新(化名)和其女友劉穎乃戈,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體亩进,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡症虑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了归薛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谍憔。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖主籍,靈堂內(nèi)的尸體忽然破棺而出习贫,到底是詐尸還是另有隱情,我是刑警寧澤千元,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布苫昌,位于F島的核電站,受9級特大地震影響幸海,放射性物質(zhì)發(fā)生泄漏蜡歹。R本人自食惡果不足惜屋厘,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望月而。 院中可真熱鬧,春花似錦议纯、人聲如沸父款。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽憨攒。三九已至,卻和暖如春阀参,著一層夾襖步出監(jiān)牢的瞬間肝集,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工蛛壳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留杏瞻,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓衙荐,卻偏偏與公主長得像捞挥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子忧吟,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

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

  • 設計模式概述 在學習面向?qū)ο笃叽笤O計原則時需要注意以下幾點:a) 高內(nèi)聚砌函、低耦合和單一職能的“沖突”實際上,這兩者...
    彥幀閱讀 3,737評論 0 14
  • 一溜族、工廠模式簡介 意圖定義一個創(chuàng)建對象的接口讹俊,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創(chuàng)建過程延遲到子類進...
    怡紅快綠閱讀 597評論 0 0
  • 一煌抒、工廠模式主要是為創(chuàng)建對象提供過渡接口仍劈,以便將創(chuàng)建對象的具體過程屏蔽隔離起來,達到提高靈活性的目的摧玫。 工廠模式在...
    李序鍇閱讀 556評論 0 0
  • 在java中耳奕,通常使用new操作符創(chuàng)建對象的實例。但是在一些情況下诬像,new操作符直接生成對象會帶來一些問題屋群,例如:...
    步積閱讀 862評論 2 3
  • 買包是一個讓人開心的話題,新鮮感讓女人保持美麗的心情坏挠。厭倦了時髦又容易撞包的大牌款芍躏,還是尋覓一下鮮嫩的小眾包,來看...
    RANu閱讀 288評論 0 0