從零開(kāi)始學(xué)設(shè)計(jì)模式(一)——工廠模式

工廠模式

工廠模式也被稱(chēng)之為虛擬構(gòu)造函數(shù)(Virtual Constructor)状蜗,是Java中最常用的設(shè)計(jì)模式之一雹姊。這種類(lèi)型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。

在工廠模式中手销,我們?cè)趧?chuàng)建對(duì)象時(shí)不會(huì)對(duì)客戶端暴露創(chuàng)建邏輯,并且是通過(guò)使用一個(gè)共同的接口來(lái)指向新創(chuàng)建的對(duì)象

意圖

定義用于創(chuàng)建對(duì)象的接口图张,但是讓子類(lèi)決定實(shí)例化哪個(gè)類(lèi)锋拖。factory方法允許類(lèi)將實(shí)例化推遲到子類(lèi)

主要解決:接口選擇的問(wèn)題。

何時(shí)使用:我們明確地計(jì)劃不同條件下創(chuàng)建不同實(shí)例時(shí)埂淮。

如何解決:讓其子類(lèi)實(shí)現(xiàn)工廠接口姑隅,返回的也是一個(gè)抽象的產(chǎn)品。

關(guān)鍵代碼:創(chuàng)建過(guò)程在其子類(lèi)執(zhí)行倔撞。

解釋

現(xiàn)實(shí)世界的例子

鐵匠制造武器讲仰。精靈需要精靈武器,獸人需要獸人武器痪蝇。根據(jù)手頭的顧客鄙陡,召集合適類(lèi)型的鐵匠

簡(jiǎn)而言之

它提供了一種將實(shí)例化邏輯委托給子類(lèi)的方法

維基百科說(shuō)

In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.
(在基于類(lèi)的編程中,factory方法模式是一種創(chuàng)建模式躏啰,它使用factory方法來(lái)處理創(chuàng)建對(duì)象的問(wèn)題趁矾,而不必指定將要?jiǎng)?chuàng)建的對(duì)象的確切類(lèi)。這是通過(guò)調(diào)用factory方法(在接口中指定并由子類(lèi)實(shí)現(xiàn)给僵,或者在基類(lèi)中實(shí)現(xiàn)并可選地由派生類(lèi)重寫(xiě))來(lái)實(shí)現(xiàn)的毫捣,而不是通過(guò)調(diào)用構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)的。)

程序代碼示例

以現(xiàn)實(shí)世界的例子鐵匠制造武器為例子帝际,需要什么樣的武器類(lèi)型我們就召喚對(duì)應(yīng)類(lèi)型的鐵匠蔓同。程序類(lèi)圖如下:


鐵匠接口實(shí)現(xiàn)類(lèi)圖.png

首先我們有一個(gè)鐵匠接口(定義了一個(gè)制造武器的方法)和一些精靈鐵匠、獸人鐵匠實(shí)現(xiàn)類(lèi):

public interface Blacksmith {
  Weapon manufactureWeapon(WeaponType weaponType);
}

public class ElfBlacksmith implements Blacksmith {
  public Weapon manufactureWeapon(WeaponType weaponType) {
    return new ElfWeapon(weaponType);
  }
}

public class OrcBlacksmith implements Blacksmith {
  public Weapon manufactureWeapon(WeaponType weaponType) {
    return new OrcWeapon(weaponType);
  }
}

其次我們有一個(gè)武器接口(定義了一個(gè)獲取武器類(lèi)型的方法)和一些精靈武器蹲诀、獸人武器實(shí)現(xiàn)類(lèi):

/**
 * Weapon interface.
 */
public interface Weapon {

  WeaponType getWeaponType();

}
/**
 * ElfWeapon.
 */
public class ElfWeapon implements Weapon {

  private WeaponType weaponType;

  public ElfWeapon(WeaponType weaponType) {
    this.weaponType = weaponType;
  }

  @Override
  public String toString() {
    return "Elven " + weaponType;
  }

  @Override
  public WeaponType getWeaponType() {
    return weaponType;
  }
}

/**
 * OrcWeapon.
 */
public class OrcWeapon implements Weapon {

  private WeaponType weaponType;

  public OrcWeapon(WeaponType weaponType) {
    this.weaponType = weaponType;
  }

  @Override
  public String toString() {
    return "Orcish " + weaponType;
  }

  @Override
  public WeaponType getWeaponType() {
    return weaponType;
  }
}

最后斑粱,隨著顧客的到來(lái),正確類(lèi)型的鐵匠被召喚出來(lái)脯爪,要求制造武器

public class App {

  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);

  private final Blacksmith blacksmith;
  
  /**
   * Creates an instance of <code>App</code> which will use <code>blacksmith</code> to manufacture 
   * the weapons for war.
   * <code>App</code> is unaware which concrete implementation of {@link Blacksmith} it is using.
   * The decision of which blacksmith implementation to use may depend on configuration, or
   * the type of rival in war.
   * @param blacksmith a non-null implementation of blacksmith
   */
  public App(Blacksmith blacksmith) {
    this.blacksmith = blacksmith;
  }
  
  /**
   * Program entry point
   * 
   * @param args command line args
   */
  public static void main(String[] args) {
    // Lets go to war with Orc weapons
    App app = new App(new OrcBlacksmith());
    app.manufactureWeapons();
    
    // Lets go to war with Elf weapons
    app = new App(new ElfBlacksmith());
    app.manufactureWeapons();
  }
  
  private void manufactureWeapons() {
    Weapon weapon;
    weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
    LOGGER.info(weapon.toString());
    weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
    LOGGER.info(weapon.toString());
  }
}

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

app類(lèi)運(yùn)行結(jié)果輸出.png

適用場(chǎng)景

當(dāng)遇到如下三種情況時(shí)则北,應(yīng)使用工廠模式:

  1. 一個(gè)類(lèi)不能預(yù)測(cè)它必須創(chuàng)建的對(duì)象的類(lèi)
  2. 一個(gè)類(lèi)希望它的子類(lèi)指定它創(chuàng)建的對(duì)象
  3. 類(lèi)將責(zé)任委托給幾個(gè)助手子類(lèi)中的一個(gè),并且你希望本地化哪個(gè)助手子類(lèi)是委托的責(zé)任

Java中的現(xiàn)實(shí)例子

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

優(yōu)點(diǎn):
1痕慢、一個(gè)調(diào)用者想創(chuàng)建一個(gè)對(duì)象尚揣,只要知道其名稱(chēng)就可以了。
2守屉、擴(kuò)展性高惑艇,如果想增加一個(gè)產(chǎn)品,只要擴(kuò)展一個(gè)工廠類(lèi)就可以。
3滨巴、屏蔽產(chǎn)品的具體實(shí)現(xiàn)思灌,調(diào)用者只關(guān)心產(chǎn)品的接口

缺點(diǎn):
每次增加一個(gè)產(chǎn)品時(shí),都需要增加一個(gè)具體實(shí)現(xiàn)類(lèi)和修改對(duì)象實(shí)現(xiàn)工廠恭取,使得系統(tǒng)中類(lèi)的個(gè)數(shù)成倍增加泰偿,在一定程度上增加了系統(tǒng)的復(fù)雜度,同時(shí)也增加了系統(tǒng)具體類(lèi)的依賴蜈垮。這并不是什么好事

寫(xiě)在最后

工廠模式作為一種創(chuàng)建類(lèi)模式耗跛,在任何需要生成復(fù)雜對(duì)象的地方,都可以使用工廠模式攒发,比如設(shè)計(jì)一個(gè)連接服務(wù)器的框架调塌,需要三個(gè)協(xié)議,"POP3"惠猿、"IMAP"羔砾、"HTTP",可以把這三個(gè)作為產(chǎn)品類(lèi)偶妖,共同實(shí)現(xiàn)一個(gè)通訊接口姜凄。

對(duì)于簡(jiǎn)單對(duì)象,特別是只需要通過(guò)new就可以完成創(chuàng)建的對(duì)象趾访,無(wú)需使用工廠模式态秧,因?yàn)槭褂霉S模式必然要引入一個(gè)工廠類(lèi),這會(huì)增加系統(tǒng)的復(fù)雜度扼鞋,切不可為了設(shè)計(jì)模式而模式申鱼。

下一篇文章我們將在工廠模式的基礎(chǔ)上繼續(xù)延伸介紹抽象工廠模式,難度系統(tǒng)為中級(jí)

碼字不易云头,各位看官喜歡的話润讥,請(qǐng)給點(diǎn)個(gè)贊??,如果你對(duì)接下來(lái)的文章有什么建議或者要求可在評(píng)論中積極留言盘寡,謝謝大家!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撮慨,一起剝皮案震驚了整個(gè)濱河市竿痰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌砌溺,老刑警劉巖影涉,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異规伐,居然都是意外死亡蟹倾,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)鲜棠,“玉大人肌厨,你說(shuō)我怎么就攤上這事』砺剑” “怎么了柑爸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)盒音。 經(jīng)常有香客問(wèn)我表鳍,道長(zhǎng),這世上最難降的妖魔是什么祥诽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任譬圣,我火速辦了婚禮,結(jié)果婚禮上雄坪,老公的妹妹穿的比我還像新娘厘熟。我一直安慰自己,他們只是感情好诸衔,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布盯漂。 她就那樣靜靜地躺著,像睡著了一般笨农。 火紅的嫁衣襯著肌膚如雪就缆。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天谒亦,我揣著相機(jī)與錄音竭宰,去河邊找鬼。 笑死份招,一個(gè)胖子當(dāng)著我的面吹牛切揭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锁摔,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼廓旬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了谐腰?” 一聲冷哼從身側(cè)響起孕豹,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎十气,沒(méi)想到半個(gè)月后励背,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡砸西,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年叶眉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了址儒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡衅疙,死狀恐怖莲趣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情炼蛤,我是刑警寧澤妖爷,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站理朋,受9級(jí)特大地震影響絮识,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嗽上,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一次舌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兽愤,春花似錦彼念、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至洼畅,卻和暖如春吩案,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背帝簇。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工徘郭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丧肴。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓残揉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親芋浮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抱环,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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

  • 設(shè)計(jì)模式概述 在學(xué)習(xí)面向?qū)ο笃叽笤O(shè)計(jì)原則時(shí)需要注意以下幾點(diǎn):a) 高內(nèi)聚、低耦合和單一職能的“沖突”實(shí)際上纸巷,這兩者...
    彥幀閱讀 3,734評(píng)論 0 14
  • 文章部分內(nèi)容轉(zhuǎn)載自:http://blog.csdn.net/zhangerqing 一江醇、設(shè)計(jì)模式的分類(lèi) 總體來(lái)說(shuō)...
    j_cong閱讀 2,058評(píng)論 0 20
  • 設(shè)計(jì)模式匯總 一、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用何暇、多...
    MinoyJet閱讀 3,906評(píng)論 1 15
  • 你還好嗎裆站? 好呀! 事情已經(jīng)過(guò)去兩三年了,想起來(lái)宏胯,滿滿的回憶羽嫡,感謝生命中出現(xiàn)的每一個(gè)人,我把故...
    叫我大寶吧閱讀 163評(píng)論 0 0
  • 有人說(shuō)發(fā)型是男人的第二張臉,這么說(shuō)或許有點(diǎn)夸張了氛赐,但很多時(shí)候魂爪,發(fā)型的合適與否,真的能對(duì)顏值艰管、氣質(zhì)的改變起到很大的作...
    愚笨閱讀 2,148評(píng)論 0 8