淺談設計模式4——簡單工廠與工廠模式


書上是三個模式——簡單工廠模式、工廠模式、抽象工廠模式,一塊說。對于昨天實在沒有休息好的狀態(tài)下,看到如此混亂的景象,確實有點受不了。好在后面一遍又一遍重復,總算是理解了。但是,既然是記筆記,也是給別人看,那么我覺得拆開來說或許更加明白。

1、背景
書上用pizza來打比方,其實還是挺愛吃,但是名字太繞口,而且也不熟悉。所以還是用餃子我覺得會更加親切些——我最愛吃的。
現(xiàn)在我要開一家餃子館,供應各種口味的餃子,三鮮餡,胡蘿卜羊肉餡,西胡蝦仁餡,芹菜牛肉餡,豬肉大蔥餡,豬肉白菜餡——看來好吃的說起來都沒完沒了。
最開始的想法是,按照如下步驟建立餃子:
1)用餃子抽象類建立餃子對象實體。
2)包餃子。
3)煮餃子。
4)裝盤,配醬油和醋。
5)上桌或打包外賣。
實現(xiàn)成的代碼如下——為了不讓很多的名詞困擾,此處直接采用更加形式化的命名方法:

//產(chǎn)品類型
abstract class ProductBase
{
    @Override
    public String toString() {
        return "productbase";
    }
}

class Product1 extends ProductBase
{
    @Override
    public String toString() {
        return "product1";
    }
}

class Product2 extends ProductBase
{
    @Override
    public String toString() {
        return "product2";
    }
}

//商店
class Store
{
    ProductBase product;
    public void  create(String product) {
        if(product.equals("product1"))
            this.product=new Product1();
        else if(product.equals("product2"))
            this.product=new Product2();
        
        //后續(xù)的操作
        //包餃子();
        //煮餃子();
        //裝盤,配醬油和醋();
        //上桌或打包();
    }
}

上面的代碼將創(chuàng)建餃子對象和對餃子的后續(xù)的加工操作,嚴重耦合,造成以下兩個比較嚴重的問題:
1)一個函數(shù)中的代碼量過大,而且隨著新類型產(chǎn)品研發(fā),這個函數(shù)將越來越大,不容易維護。
2)當餐館發(fā)明新的餃子時,就需要修改sell()方法。原來類的封裝性就遭到破壞。

2、簡單工廠模式
根據(jù)上面的問題,我們自然想到的是將創(chuàng)建產(chǎn)品對象的那部分代碼進行封裝,這樣就實現(xiàn)了工廠模式。簡單工廠模式如下:

//產(chǎn)品類型
abstract class ProductBase
{
    @Override
    public String toString() {
        return "productbase";
    }
}

class Product1 extends ProductBase
{
    @Override
    public String toString() {
        return "product1";
    }
}

class Product2 extends ProductBase
{
    @Override
    public String toString() {
        return "product2";
    }
}

class ProductFactory
{
    public ProductBase create(String product)
    {
        if(product.equals("product1"))
            return new Product1();
        else if(product.equals("product2"))
            return new Product2();
        else return null;
    }
}

//商店
class Store
{
    ProductBase product;
    ProductFactory productFactory;
    
    public Store(ProductFactory productFactory)
    {
        this.productFactory=productFactory;
    }
    
    public void  create(String product) {
    /*  if(product.equals("product1"))
            this.product=new Product1();
        else if(product.equals("product2"))
            this.product=new Product2();
    */
        this.productFactory.create(product);
        //后續(xù)的操作
        //包餃子();
        //煮餃子();
        //裝盤,配醬油和醋();
        //上桌或打包();
    }
}

“簡單工廠模式”是將對象的生成和使用進行分離,以組合的方式,當創(chuàng)建使用某一類對象的實體時(如Store類的對象),將真正創(chuàng)建對象的工廠傳入。從而獲得以下兩方面的收益:
1)工廠可以在動態(tài)運行時的時候指定。比如我現(xiàn)在不打算開餃子店了,想做包子,由于包子和餃子的后續(xù)工作都是一樣的,所以只需把制作包子的工廠傳入Store類中就行。
2)產(chǎn)品、制作、使用三者進行了有效分離。產(chǎn)品的分離已經(jīng)在前面的策略模式中說道——用抽象接口來“臨時”代替具體類,占位置,將創(chuàng)建對象實體推遲到運行時。制作即使用了簡單工廠模式,而使用即為Store類。這樣就在一定程度上,將類之間的耦合度降到很低。

3、工廠模式
相對于簡單工廠模式,工廠模式的耦合度相對來說比較大。之所以比較大,先看下面的例子。
假設餃子店生意不錯,規(guī)模逐漸增大,最后成立一個實業(yè)公司——餃子餐飲有限公司,而且設立了各個分部——華北子公司,東北子公司,華南子公司,華東子公司,中西部子公司。為了保證所有公司生產(chǎn)的餃子質量過關,公司決定控制生產(chǎn)流程。所有子公司可以根據(jù)當?shù)靥禺a(chǎn),選擇自己的餡料,但是制作工藝必須嚴格按照公司的流程,比如每個面皮必須為10g,直徑5CM的圓面片。餡料必須20g。
這樣,既增加了靈活性——子公司可以根據(jù)當?shù)靥禺a(chǎn)選擇餡料,又保證了質量——嚴格按照母公司的規(guī)程辦事。

說這么多,我想“簡單工廠模式”和“工廠模式”應用的場景大家也應該能看出來了。
1)簡單工廠模式是針對只有一個使用者的情況來說,即程序中只有一個Store類,這個Store類可以使用多用“工廠類”來為自己加工產(chǎn)品。
2)工廠模式不同,它是針對某個基類的一堆子類,在保證某些流程不改變的情況下, 允許子類有自己的行為特征。也就是說,基類規(guī)定了框架,而子類只能在框架的基礎上修補、更改。

那么看下面的代碼就比較能說明問題了:

abstract class ProductBase
{
    @Override
    public String toString() {
        return "productbase";
    }
}
class a1 extends ProductBase
{
    @Override
    public String toString() {
        return "a1";
    }
}
class a2 extends ProductBase
{
    @Override
    public String toString() {
        return "a2";
    }
}
class b1 extends ProductBase
{
    @Override
    public String toString() {
        return "b1";
    }
}
class b2 extends ProductBase
{
    @Override
    public String toString() {
        return "b2";
    }
}


//創(chuàng)建工廠基類
abstract class FactoryBase
{
    public abstract ProductBase create(String type);
    final public ProductBase sell(String type)
    {
        ProductBase productBase;
        productBase=create(type);
        //后續(xù)的操作
        //包餃子();
        //煮餃子();
        //裝盤,配醬油和醋();
        //上桌或打包();
        return productBase;
    }
}
//實現(xiàn)工廠派生類
class Factory1 extends FactoryBase
{
    @Override
    public ProductBase create(String type) {
        ProductBase productBase=null;
        if(type.equals("a1"))
            productBase=new a1();
        else if(type.equals("a2"))
            productBase=new a2();
        return productBase;
    }
}

class Factory2 extends FactoryBase
{
    @Override
    public ProductBase create(String type) {
        ProductBase productBase=null;
        if(type.equals("b1"))
            productBase=new b1();
        else if(type.equals("b2"))
            productBase=new b2();
        return productBase;
    }
}

如上代碼所示:
1)分別建立產(chǎn)品基類、工廠基類。由產(chǎn)品基類,根據(jù)不同地區(qū)(地區(qū)a和地區(qū)b),構建了子類產(chǎn)品。相應的,也構建了不同的子類工廠。
2)基類工廠中,sell()方法作為對外統(tǒng)一方法,控制生產(chǎn)總流程,因此生命為final方法。而create()方法則因地制宜,按照不同地區(qū)特點,生產(chǎn)特定的產(chǎn)品。

這樣,工廠方法既保證了修改的靈活性,也保證了某些必要操作不會被修改。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

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

  • 設計模式匯總 一、基礎知識 1. 設計模式概述 定義:設計模式(Design Pattern)是一套被反復使用、多...
    MinoyJet閱讀 3,961評論 1 15
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內(nèi)部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,733評論 18 399
  • 一個UML類圖 類之間的關系 類的繼承結構表現(xiàn)在UML中為:泛化(generalize)與實現(xiàn)(realize) ...
    僚機KK閱讀 656評論 0 0
  • 設計模式基本原則 開放-封閉原則(OCP),是說軟件實體(類、模塊、函數(shù)等等)應該可以拓展,但是不可修改。開-閉原...
    西山薄涼閱讀 3,843評論 3 14
  • 簡單工廠模式雖然簡單,但存在一個很嚴重的問題。當系統(tǒng)中需要引入新產(chǎn)品時,由于靜態(tài)工廠方法通過所傳入?yún)?shù)的不同來創(chuàng)建...
    justCode_閱讀 1,200評論 1 9