工廠(chǎng)模式--簡(jiǎn)單工廠(chǎng)模式

設(shè)計(jì)模式

1 工廠(chǎng)模式簡(jiǎn)介

1.1 定義

簡(jiǎn)單工廠(chǎng)模式屬于創(chuàng)建型模式又叫做靜態(tài)工廠(chǎng)方法模式孔轴,它屬于類(lèi)創(chuàng)建型模式墩剖。在簡(jiǎn)單工廠(chǎng)模式中界轩,可以根據(jù)參數(shù)的不同返回不同類(lèi)的實(shí)例反症。
簡(jiǎn)單工廠(chǎng)模式專(zhuān)門(mén)定義一個(gè)類(lèi)來(lái)負(fù)責(zé)創(chuàng)建其他類(lèi)的實(shí)例,被創(chuàng)建的實(shí)例通常都具有共同的父類(lèi)存捺。

1.2 簡(jiǎn)單工廠(chǎng)模式結(jié)構(gòu)圖

20160211134612096.png
  • Factory:工廠(chǎng)類(lèi)槐沼,簡(jiǎn)單工廠(chǎng)模式的核心曙蒸,它負(fù)責(zé)實(shí)現(xiàn)創(chuàng)建所有實(shí)例的內(nèi)部邏輯。工廠(chǎng)類(lèi)的創(chuàng)建產(chǎn)品類(lèi)的方法可以被外界直接調(diào)用岗钩,創(chuàng)建所需的產(chǎn)品對(duì)象纽窟。
  • IProduct:抽象產(chǎn)品類(lèi),簡(jiǎn)單工廠(chǎng)模式所創(chuàng)建的所有對(duì)象的父類(lèi)兼吓,它負(fù)責(zé)描述所有實(shí)例所共有的公共接口臂港。
  • Product:具體產(chǎn)品類(lèi),是簡(jiǎn)單工廠(chǎng)模式的創(chuàng)建目標(biāo)视搏。

2 簡(jiǎn)單工廠(chǎng)模式簡(jiǎn)單實(shí)現(xiàn)

這里我們用生產(chǎn)電腦來(lái)舉例审孽,假設(shè)有一個(gè)電腦的代工生產(chǎn)商,它目前已經(jīng)可以代工生產(chǎn)聯(lián)想電腦了浑娜,隨著業(yè)務(wù)的拓展瓷胧,這個(gè)代工生產(chǎn)商還要生產(chǎn)惠普和華碩的電腦,這樣我們就需要用一個(gè)單獨(dú)的類(lèi)來(lái)專(zhuān)門(mén)生產(chǎn)電腦棚愤,這就用到了簡(jiǎn)單工廠(chǎng)模式。下面我們來(lái)實(shí)現(xiàn)簡(jiǎn)單工廠(chǎng)模式:

2.1 創(chuàng)建抽象產(chǎn)品類(lèi)

我們創(chuàng)建一個(gè)電腦的抽象產(chǎn)品類(lèi)杂数,他有一個(gè)抽象方法用于啟動(dòng)電腦:

public abstract class Computer {
    /**
     * 產(chǎn)品的抽象方法宛畦,由具體的產(chǎn)品類(lèi)去實(shí)現(xiàn)
     */
    public abstract void start();
}

2.2 創(chuàng)建具體產(chǎn)品類(lèi)

接著我們創(chuàng)建各個(gè)品牌的電腦,他們都繼承了他們的父類(lèi)Computer 揍移,并實(shí)現(xiàn)了父類(lèi)的start方法:

2.2.1 聯(lián)想電腦:

public class LenovoComputer extends Computer{
    @Override
    public void start() {
        System.out.println("聯(lián)想電腦啟動(dòng)");
    }

2.2.2 惠普電腦:

public class HpComputer extends Computer{
    @Override
    public void start() {
        System.out.println("惠普電腦啟動(dòng)");
    }
}

2.2.3 華碩電腦:

public class AsusComputer extends Computer {
    @Override
    public void start() {
        System.out.println("華碩電腦啟動(dòng)");
    }
}

2.3 創(chuàng)建工廠(chǎng)類(lèi)

接下來(lái)創(chuàng)建一個(gè)工廠(chǎng)類(lèi)次和,它提供了一個(gè)靜態(tài)方法createComputer用來(lái)生產(chǎn)電腦。你只需要傳入你想生產(chǎn)的電腦的品牌那伐,它就會(huì)實(shí)例化相應(yīng)品牌的電腦對(duì)象:

public class ComputerFactory {
    public static Computer createComputer(String type){
        Computer mComputer=null;
        switch (type) {
            case "lenovo":
                mComputer=new LenovoComputer();
               break;
            case "hp":
                mComputer=new HpComputer();
                break;
            case "asus":
                mComputer=new AsusComputer();
                break;

        }
        return mComputer;
    }
}

2.4 客戶(hù)端調(diào)用工廠(chǎng)類(lèi)

客戶(hù)端調(diào)用工廠(chǎng)類(lèi)踏施,傳入“hp”生產(chǎn)出惠普電腦并調(diào)用該電腦對(duì)象的start方法:

public class CreatComputer {
    public static void main(String[]args){
      ComputerFactory.createComputer("hp").start();
    }
}

2.5 第二種實(shí)現(xiàn)方法


public class RuleConfigParserFactory {
  private static final Map<String, RuleConfigParser> cachedParsers = new HashMap<>();

  static {
    cachedParsers.put("json", new JsonRuleConfigParser());
    cachedParsers.put("xml", new XmlRuleConfigParser());
    cachedParsers.put("yaml", new YamlRuleConfigParser());
    cachedParsers.put("properties", new PropertiesRuleConfigParser());
  }

  public static IRuleConfigParser createParser(String configFormat) {
    if (configFormat == null || configFormat.isEmpty()) {
      return null;//返回null還是IllegalArgumentException全憑你自己說(shuō)了算
    }
    IRuleConfigParser parser = cachedParsers.get(configFormat.toLowerCase());
    return parser;
  }
}

為了節(jié)省內(nèi)存和對(duì)象創(chuàng)建的時(shí)間,我們可以將 parser 事先創(chuàng)建好緩存起來(lái)罕邀。

3 優(yōu)點(diǎn)和缺點(diǎn)

3.1 優(yōu)點(diǎn)

  • 工廠(chǎng)類(lèi)含有必要的判斷邏輯畅形,可以決定在什么時(shí)候創(chuàng)建哪一個(gè)產(chǎn)品類(lèi)的實(shí)例,客戶(hù)端可以免除直接創(chuàng)建產(chǎn)品對(duì)象的責(zé)任诉探,而僅僅“消費(fèi)”產(chǎn)品日熬;簡(jiǎn)單工廠(chǎng)模式通過(guò)這種做法實(shí)現(xiàn)了對(duì)責(zé)任的分割,它提供了專(zhuān)門(mén)的工廠(chǎng)類(lèi)用于創(chuàng)建對(duì)象肾胯。
  • 客戶(hù)端無(wú)須知道所創(chuàng)建的具體產(chǎn)品類(lèi)的類(lèi)名竖席,只需要知道具體產(chǎn)品類(lèi)所對(duì)應(yīng)的參數(shù)即可,對(duì)于一些復(fù)雜的類(lèi)名敬肚,通過(guò)簡(jiǎn)單工廠(chǎng)模式可以減少使用者的記憶量毕荐。
  • 通過(guò)引入配置文件,可以在不修改任何客戶(hù)端代碼的情況下更換和增加新的具體產(chǎn)品類(lèi)艳馒,在一定程度上提高了系統(tǒng)的靈活性憎亚。

3.2 缺點(diǎn)

  • 由于工廠(chǎng)類(lèi)集中了所有產(chǎn)品創(chuàng)建邏輯,一旦不能正常工作,整個(gè)系統(tǒng)都要受到影響虽填。
  • 使用簡(jiǎn)單工廠(chǎng)模式將會(huì)增加系統(tǒng)中類(lèi)的個(gè)數(shù)丁恭,在一定程序上增加了系統(tǒng)的復(fù)雜度和理解難度。
  • 系統(tǒng)擴(kuò)展困難斋日,一旦添加新產(chǎn)品就不得不修改工廠(chǎng)邏輯牲览,同樣破壞了“開(kāi)閉原則”;在產(chǎn)品類(lèi)型較多時(shí)恶守,有可能造成工廠(chǎng)邏輯過(guò)于復(fù)雜第献,不利于系統(tǒng)的擴(kuò)展和維護(hù)
  • 簡(jiǎn)單工廠(chǎng)模式由于使用了靜態(tài)工廠(chǎng)方法兔港,造成工廠(chǎng)角色無(wú)法形成基于繼承的等級(jí)結(jié)構(gòu)庸毫。

4 適用環(huán)境

在以下情況下可以使用簡(jiǎn)單工廠(chǎng)模式:

  • 工廠(chǎng)類(lèi)負(fù)責(zé)創(chuàng)建的對(duì)象比較少:由于創(chuàng)建的對(duì)象較少,不會(huì)造成工廠(chǎng)方法中的業(yè)務(wù)邏輯太過(guò)復(fù)雜衫樊。
  • 客戶(hù)端只知道傳入工廠(chǎng)類(lèi)的參數(shù)飒赃,對(duì)于如何創(chuàng)建對(duì)象不關(guān)心:客戶(hù)端既不需要關(guān)心創(chuàng)建細(xì)節(jié),甚至連類(lèi)名都不需要記住科侈,只需要知道類(lèi)型所對(duì)應(yīng)的參數(shù)载佳。

5 模式應(yīng)用

  • JDK類(lèi)庫(kù)中廣泛使用了簡(jiǎn)單工廠(chǎng)模式,如工具類(lèi)java.text.DateFormat臀栈,它用于格式化一個(gè)本地日期或者時(shí)間蔫慧。
public final static DateFormat getDateInstance(); 
public final static DateFormat getDateInstance(int style); 
public final static DateFormat getDateInstance(int style,Locale locale);
  • 獲取不同加密算法的密鑰生成器。
KeyGenerator keyGen=KeyGenerator.getInstance("DESede");

6 違背開(kāi)閉原則

對(duì)于上面兩種簡(jiǎn)單工廠(chǎng)模式的實(shí)現(xiàn)方法权薯,如果我們要添加新的 parser姑躲,那勢(shì)必要改動(dòng)到 RuleConfigParserFactory 的代碼,那這是不是違反開(kāi)閉原則呢盟蚣?實(shí)際上黍析,如果不是需要頻繁地添加新的 parser,只是偶爾修改一下 RuleConfigParserFactory 代碼刁俭,稍微不符合開(kāi)閉原則橄仍,也是完全可以接受的。

盡管簡(jiǎn)單工廠(chǎng)模式的代碼實(shí)現(xiàn)中牍戚,有多處 if 分支判斷邏輯侮繁,違背開(kāi)閉原則,但權(quán)衡擴(kuò)展性和可讀性如孝,這樣的代碼實(shí)現(xiàn)在大多數(shù)情況下(比如宪哩,不需要頻繁地添加 parser,也沒(méi)有太多的 parser)是沒(méi)有問(wèn)題的第晰。

參考

設(shè)計(jì)模式(四)簡(jiǎn)單工廠(chǎng)模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锁孟,一起剝皮案震驚了整個(gè)濱河市彬祖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌品抽,老刑警劉巖储笑,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異圆恤,居然都是意外死亡突倍,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)盆昙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)羽历,“玉大人,你說(shuō)我怎么就攤上這事淡喜★趿祝” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵炼团,是天一觀的道長(zhǎng)澎嚣。 經(jīng)常有香客問(wèn)我,道長(zhǎng)瘟芝,這世上最難降的妖魔是什么币叹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮模狭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘踩衩。我一直安慰自己嚼鹉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布驱富。 她就那樣靜靜地躺著锚赤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪褐鸥。 梳的紋絲不亂的頭發(fā)上线脚,一...
    開(kāi)封第一講書(shū)人閱讀 52,246評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音叫榕,去河邊找鬼浑侥。 笑死,一個(gè)胖子當(dāng)著我的面吹牛晰绎,可吹牛的內(nèi)容都是我干的寓落。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼荞下,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼伶选!你這毒婦竟也來(lái)了史飞?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤仰税,失蹤者是張志新(化名)和其女友劉穎构资,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體陨簇,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吐绵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了塞帐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拦赠。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖葵姥,靈堂內(nèi)的尸體忽然破棺而出荷鼠,到底是詐尸還是另有隱情,我是刑警寧澤榔幸,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布允乐,位于F島的核電站,受9級(jí)特大地震影響削咆,放射性物質(zhì)發(fā)生泄漏牍疏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一拨齐、第九天 我趴在偏房一處隱蔽的房頂上張望鳞陨。 院中可真熱鬧,春花似錦瞻惋、人聲如沸厦滤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)掏导。三九已至,卻和暖如春羽峰,著一層夾襖步出監(jiān)牢的瞬間趟咆,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工梅屉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留值纱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓坯汤,卻偏偏與公主長(zhǎng)得像计雌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子玫霎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

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