嘻哈說:設計模式之工廠方法模式

番茄課堂_懶人發表於2018-10-23

1、嘻哈說

這首歌還沒寫不能發

因為本節的工廠方法模式與抽象工廠模式存在關聯度,所以會在下一節《抽象工廠模式》中混成一首歌發。

2、簡單工廠模式的定義

現實中的工廠,是用來生產產品的,而程式碼中的工廠,則是建立物件的,

用來建立物件,那肯定就是建立型模式了。

我們經常會用到三種和工廠相關的設計模式:簡單工廠模式、工廠方法模式、抽象工廠模式。

這節我們們要說的是——工廠方法模式。

不過,再說工廠方法之前,我們要先說下簡單工廠模式。我們從簡單的開始入手,由簡入繁。

簡單工廠模式呢,它不屬於Gof23種設計模式之一,但它在實際的專案中經常被用到,所以我們還是很有必要學習,並且它的思想也非常簡單,可以說是工廠方法模式的一個引導。

我們來看一下簡單工廠方法的定義。

又稱為靜態工廠模式,由一個工廠物件決定建立出哪一種產品類的例項。

注意這裡的定義,是一個工廠物件

怎麼實現呢?實現的套路是什麼?

定義一個工廠類,可以根據引數的不同返回不同類的例項,被建立的例項通常有共同的父類。

3、場景

場景與建造者模式有點類似,還是熟悉的餃子,還是熟悉的配方,還是熟悉的味道,扯遠了...

美食餃子

番茄餐廳的後廚。

廚師長:老闆,我聽說隔壁餐廳買來了一個機器,包餃子神器,一輸入引數,餃子直接出鍋,高科技呀,跟餃子工廠似的。

老闆:你的意思是我們們也去買個?

廚師長:嗯,我是想提這個建議的,一鍵出餃子,想想心裡還有點小激動呢。

老闆:你不會是為了圖省事吧?

求生欲極強的廚師長:當然不是,我是覺得餃子神器效率高,能夠給我們飯店帶來更大的價值。

老闆:嗯,那我同意了,錢從你工資里扣。

委屈的廚師長:老闆,這樣不合適吧?我上有老,下有...

老闆:打住,逗你的,看把你給嚇得。效率提高但味道降低,這種神器我們們飯店不會用的。

我們今天的例子,就是餃子工廠,可以生產各種餃子餡、皮。

4、簡單工廠模式

簡單工廠UML圖

簡單工廠模式的UML類圖。

package com.fanqiekt.factory.simple;

/**
 * 餃子餡
 *
 * @Author: 番茄課堂-懶人
 */
public interface IStuffing {

    void make();

}
複製程式碼

IStuffing:產品(餃子餡)的介面,共有的父類。

make()就是製造餃子皮的方法。

package com.fanqiekt.factory.simple;

/**
 * 豬肉大蔥餡
 * @Author: 番茄課堂-懶人
 */
public class PorkStuffing implements IStuffing {

    @Override
    public void make() {
        System.out.println("製作豬肉大蔥餡");
    }

}
複製程式碼
package com.fanqiekt.factory.simple;

/**
 * 茴香雞蛋餡
 * @Author: 番茄課堂-懶人
 */
public class FoeniculumVulgareStuffing implements IStuffing {

    @Override
    public void make() {
        System.out.println("製作茴香雞蛋餡");
    }

}
複製程式碼
package com.fanqiekt.factory.simple;

/**
 * 韭菜雞蛋餡
 * @Author: 番茄課堂-懶人
 */
public class ChineseChivesStuffing implements IStuffing {

    @Override
    public void make() {
        System.out.println("製作韭菜雞蛋餡");
    }

}
複製程式碼

具體的產品類,餃子餡中的大戶:豬肉大蔥餡、茴香雞蛋餡、韭菜雞蛋餡。

package com.fanqiekt.factory.simple;

/**
 * 餃子餡工廠類
 * @Author: 番茄課堂-懶人
 */
public class StuffingFactory {
    public static IStuffing getStuffing(String key){
        IStuffing stuffing = null;
        switch (key){
            case "豬肉大蔥":
                stuffing = new PorkStuffing();
                break;
            case "韭菜雞蛋":
                stuffing = new ChineseChivesStuffing();
                break;
            case "茴香雞蛋":
                stuffing = new FoeniculumVulgareStuffing();
                break;
        }
        return stuffing;
    }
}
複製程式碼

StuffingFactory:餃子餡工廠類。

簡單工廠中只有一個工廠類,並且提供了一個靜態公有方法,可以根據引數的不同返回不同類的例項。

這也是簡單方法為什麼要被稱之為靜態工廠模式的原因。

package com.fanqiekt.factory.simple;

/**
 * 客戶端
 * @Author: 番茄課堂-懶人
 */
public class Client {

    public static void main(String args[]){
        IStuffing stuffing = StuffingFactory.getStuffing("豬肉大蔥");
        stuffing.make();

        System.out.println("------------");

        stuffing = StuffingFactory.getStuffing("韭菜雞蛋");
        stuffing.make();

        System.out.println("------------");

        stuffing = StuffingFactory.getStuffing("茴香雞蛋");
        stuffing.make();
    }

}
複製程式碼

客戶端類。

我們可以看出,簡單工廠不愧為簡單工廠,就是赤裸裸的簡單。

但簡單並不普通,它完美的展現了工廠方法的思想,讓工廠建立物件,而不是物件A去建立物件B。

這樣可以避免物件A與物件B之間的耦合。

我們執行一下,看結果。

製作豬肉大蔥餡
------------
製作韭菜雞蛋餡
------------
製作茴香雞蛋餡
複製程式碼

5、工廠方法模式的定義

如果按照簡單工廠的寫法,在不使用java的反射的前提下,擴充套件性是很差的。

如果新增一種餃子餡,必須修改工廠中的判斷。

所以我們來介紹一下另外一種工廠模式——工廠方法模式,下面,我們有請男主出場。

我們先來看看,工廠方法模式的官方定義:

定義一個用於建立物件的介面,讓子類決定例項化哪一個類。

從定義中,我們可以看出實現的套路:定一個建立物件的介面,然後每個工廠去實現該介面例項化特定的物件,這樣就使一個類的例項化延遲到其子類。

每一個產品都有相應的工廠,這就是與簡單工廠模式最大的區別。

然後,呼叫者可以自由的 選擇使用哪個工廠去建立物件。

6、工廠方法模式

工廠方法UML圖

工廠方法模式的UML類圖。

產品(餃子餡)與簡單工廠模式的程式碼一致,這裡就不貼出來了。

package com.fanqiekt.factory.method;

/**
 * 工廠介面
 * @Author: 番茄課堂-懶人
 */
public interface IFactory {

    IStuffing getStuffing();

}
複製程式碼

IFactory:工廠的介面。

定義一個用於建立物件的介面。

getStuffing()獲得產品(餃子餡)的方法,交給具體的子類來實現。使一個類的例項化延遲到其子類。

package com.fanqiekt.factory.method;

/**
 * 豬肉大蔥餡工廠
 * @Author: 番茄課堂-懶人
 */
public class PorkFactory implements IFactory {
    @Override
    public IStuffing getStuffing() {
        return new PorkStuffing();
    }
}
複製程式碼
package com.fanqiekt.factory.method;

/**
 * 茴香雞蛋餡工廠
 * @Author: 番茄課堂-懶人
 */
public class FoeniculumVulgareFactory implements IFactory {
    @Override
    public IStuffing getStuffing() {
        return new FoeniculumVulgareStuffing();
    }
}
複製程式碼
package com.fanqiekt.factory.method;

/**
 * 韭菜雞蛋餡工廠
 * @Author: 番茄課堂-懶人
 */
public class ChineseChivesFactory implements IFactory {
    @Override
    public IStuffing getStuffing() {
        return new ChineseChivesStuffing();
    }
}
複製程式碼

具體的工廠類。

為每個產品(餃子餡)提供一個工廠類:豬肉大蔥餡工廠、茴香雞蛋餡工廠、韭菜雞蛋餡工廠。

這樣的設計,擴充套件起來也非常的方便,例如增加三鮮餡,只需要增加產品類(三鮮餡)、工廠類(三鮮餡)就可以了。不會影響其他。

7、區別

簡單工廠模式,只有一個工廠類,根據引數的不同返回不同類的例項。

工廠方法模式,定義一個建立物件的介面,存在實現該介面的多個工廠類。呼叫者選擇使用哪個工廠。

8、END

從下一節課程開始,《嘻哈說——設計模式》系列的課程將不在其他渠道釋出,改為公眾號《番茄課堂》獨家釋出,期待大家的關注。

今天就先說到這裡,下一節說《抽象工廠模式》,感謝大家支援。

相關文章