iT邦幫忙

2022 iThome 鐵人賽

DAY 11
0
自我挑戰組

設計模式探索系列 第 11

[Day 11] 工廠模式 (1)

  • 分享至 

  • xImage
  •  

前言

今天前進到了第四章─ 工廠模式,這章篇幅較長,在實際運用中也非常常見,值得好好理解,不但可以運用在程式設計上,也常常在溝通時聽到這邊用simple factory,這邊用factory來做,這下終於可以完整接收這些意思了~ 就來看看這些工廠系列的模式指的是什麼設計方式吧!

前面 裝飾器模式 有提及我們需要一個有效製作各種裝飾器類別的方法,讓建立裝飾器的過程是有被好好封裝的,這章就馬上要來介紹啦!我們需要一個避免依賴關係低耦合的結構來進行實例化

製造不同種類的pizza

首先,這次的問題是要產生各種pizza,假設我們需要決定pizza種類並進行製作,最直接的寫法如下:

Pizza *orderPizza() ()
{
    Pizza *pizza = new Pizza();
    pizza->prepare();
    pizza->bake();
    pizza->cut();
    pizza->box();
    return pizza;
}

但因為有很多種口味,我們不得不new對應的實例出來,就如同第一章的產生各種鴨子
因此要加入一些判斷:

Pizza *orderPizza(string type)
{
    // Pizza *pizza = new Pizza();
    Pizza *pizza = nullptr;
    if("cheese" == type)
    {
        pizza = new CheesePizza();
    }
    else if("greek" == type)
    {
        pizza = new GreekPizza();
    }
    else if("pepperoni" == type)
    {
        pizza = new PepperoniPizza();
    }
    else
    {
        return pizza;
    }

    pizza->prepare();
    pizza->bake();
    pizza->cut();
    pizza->box();
    return pizza;
};

我們不得不new各種pizza的實例,看到這一大堆的if-else,就會覺得它有很高的機率會需要各種修改,例如新增或移除了一些pizza口味。這時回顧天字號第一原則把會變和不會變的部分隔開,我們大概知道要怎麼改了─

  • 首先把會變─就是判斷那堆pizza種類的地方抽出來,並把它放入一個工廠集散地SimplePizzaFactory裡─
class SimplePizzaFactory
{
    public:
        Pizza* createPizza(string type)
        {
            Pizza *pizza = nullptr;
            if("cheese" == type)
            {
                pizza = new CheesePizza();
            }
            else if("greek" == type)
            {
                pizza = new GreekPizza();
            }
            else if("pepperoni" == type)
            {
                pizza = new PepperoniPizza();
            }

            return pizza;
        }
};
  • 接著原本的order我們也把它放入pizza store物件:
class PizzaStore
{
    SimplePizzaFactory factory;
    public:
        PizzaStore(SimplePizzaFactory factory)
        {
            this->factory = factory;
        }

        Pizza *orderPizza(string type)
        {
            Pizza *pizza = factory.createPizza(type);
            pizza->prepare();
            pizza->bake();
            pizza->cut();
            pizza->box();
            return pizza;
        };

};

看似只是簡單地把函式一分為二,並分別放到SimplePizzaFactoryPizzaStore裡,但背後有其他意義;我們把會變的部分移過去Factory裡,對PizzaSotre這個用戶而言就被封裝了,讓用戶端不用再自己做實例化這件事;此外,這個工廠可能也有其他用戶端,這樣就不是一分為二了,且切得乾淨。
而這就是本章介紹的第一個...習慣寫法,還不算是設計模式─簡單工廠 (simple factory)

簡單工廠 (simple factory)

這不是真正的設計模式,但很常見,可以從目前的案例看看它的架構:
https://ithelp.ithome.com.tw/upload/images/20220927/201400961bF4DJqKhC.png

簡單來說,簡單工廠就是把create實例化的部分抽出,其他共通的部分保留在原本的地方,並用 "組合" 的方式連接兩者。

接下來我們來考慮更進階的情形─ 如果現在想要有不同的披薩店,可以各自生產專屬口味,但又希望其他共同的部分(prepare, bake等等)不會被改變,該怎麼做呢?
如果依照原本簡單工廠的架構,我們只有一間工廠,就必須在這個factory裡面改動各種程式碼,加入更多的if-else與pizza,不利於比較複雜的生產情形。

明天,我們來看看正式的設計模式─工廠方法。。


上一篇
[Day 10] 裝飾器模式 (2)
下一篇
[Day 12] 工廠模式 (2)
系列文
設計模式探索30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言