簡單工廠模式(Simple Factory Pattern)

簡單工廠模式算是最基本的工廠模式,經常使用到,也可以把這當成是一種編成習慣,我們用披薩店的情境來加以說明。

假設有一間披薩店,賣各式各樣的披薩,如果有人點了夏威夷披薩,就準備夏威夷披薩,送入烤箱烘烤,然後拿給消費者,假如有人點鮪魚披薩,就準備鮪魚披薩,接著烘烤並拿給消費者。

#include <iostream>
#include <string>
using namespace std;
 
class Pizza{
public:
    string m_name;
    void bake(){cout << m_name << "進行烘烤" << endl;}
    void deliver(){cout << m_name << "進行運送" << endl;}
};
class HawaiiPizza : public Pizza{
public:
    HawaiiPizza(){m_name="Hawaii";}
};
class TunaPizza : public Pizza{
public:
    TunaPizza(){m_name="Tuna";}
};

Pizza *orderPizza(string name){
    Pizza *ret;
    if(name=="Hawaii"){
        ret = new HawaiiPizza();
    }
    if(name=="Tuna"){
        ret = new TunaPizza();
    }
    ret->bake();
    ret->deliver();
    return ret;
}

int main() { 
    Pizza *myHawaiiPizza = orderPizza("Hawaii");
    Pizza *myTunaPizza = orderPizza("Tuna");

    delete myHawaiiPizza;
    delete myTunaPizza;
    return 0; 
}

在上面的程式範例中,orderPizza()函式內部依參數來實體化類別,所以當增加口味更改時,修改orderPizza()函式是不可避免的,但我們已經知道會修改甚麼地方,可以將會變動的地方取出並封裝,下面使用PizzaFactory類別來處理披薩的產生,而PizzaStore類別負責披薩產生的後續處理。

#include <iostream>
#include <string>
using namespace std; 

class Pizza{
public:
    string m_name;
    void bake(){cout << m_name << "進行烘烤" << endl;}
    void delever(){cout << m_name << "進行運送" << endl;}
};
class HawaiiPizza : public Pizza{
public:
    HawaiiPizza(){m_name="Hawaii pizza";}
};
class TunaPizza : public Pizza{
public:
    TunaPizza(){m_name="Tuna pizza";}
};

class PizzaFactory{
public:
    Pizza *createPizza(string name);
};
Pizza *PizzaFactory::createPizza(string name){
    Pizza *ret;
    if(name=="Hawaii"){
        ret = new HawaiiPizza();
    }
    if(name=="Tuna"){
        ret = new TunaPizza();
    }
    return ret;
}

class PizzaStore{
private:
    PizzaFactory m_PizzaFactory;
public:
    PizzaStore(PizzaFactory factory){m_PizzaFactory=factory;}
    Pizza *orderPizza(string name);
};
Pizza *PizzaStore::orderPizza(string name){
    Pizza *ret = m_PizzaFactory.createPizza(name);
    ret->bake();
    ret->deliver();
    return ret;
}

int main() { 
    PizzaFactory myPizzaFactory;
    PizzaStore myPizzaStore(myPizzaFactory);
    Pizza *myHawaiiPizza = myPizzaStore.orderPizza("Hawaii");
    Pizza *myTunaPizza = myPizzaStore.orderPizza("Tuna");

    delete myHawaiiPizza;
    delete myTunaPizza;
    return 0; 
}

上述例子用單一工廠,產生所有的可能類別實例,下面用類似的方式,但是讓每個產品都有各自的工廠,當產品有新增時,上述例子必須要修改工廠方法,下面方法則是增加一個新的工廠子類別,如此較符合開放封閉原則,但有會產生大量工廠子類別的缺點。

我們用HawaiiPizzaFactory和TunaPizzaFactory類別取代原本的PizzaFactory的功能,以下為程式碼。

#include <iostream>
#include <string>
using namespace std; 

class Pizza{
public:
    string m_name;
    void bake(){cout << m_name << "進行烘烤" << endl;}
    void delever(){cout << m_name << "進行運送" << endl;}
};
class HawaiiPizza : public Pizza{
public:
    HawaiiPizza(){m_name="Hawaii pizza";}
};
class TunaPizza : public Pizza{
public:
    TunaPizza(){m_name="Tuna pizza";}
};

class PizzaFactory{
public:
    virtual Pizza *createPizza() = 0;
};
class HawaiiPizzaFactory : public PizzaFactory{
public:
    Pizza *createPizza();
};
class TunaPizzaFactory : public PizzaFactory{
public:
    Pizza *createPizza();
};
Pizza *HawaiiPizzaFactory::createPizza(){
    Pizza *ret = new HawaiiPizza();
    return ret;
}
Pizza *TunaPizzaFactory::createPizza(){
    Pizza *ret = new TunaPizza();
    return ret;
}
class PizzaStore{
private:
    PizzaFactory *m_PizzaFactory;
public:
    PizzaStore(PizzaFactory *factory){m_PizzaFactory=factory;}
    void setFlavor(PizzaFactory *factory){m_PizzaFactory=factory;}
    Pizza *orderPizza();
};
Pizza *PizzaStore::orderPizza(){
    Pizza *ret = m_PizzaFactory->createPizza();
    ret->bake();
    ret->ship();
    return ret;
}

int main() { 
    HawaiiPizzaFactory myHawaiiFactory;
    PizzaStore myPizzaStore(&myHawaiiFactory);
    Pizza *myHawaiiPizza = myPizzaStore.orderPizza();

    TunaPizzaFactory myTunaFactory;
    myPizzaStore.setFlavor(&myTunaFactory);
    Pizza *myTunaPizza = myPizzaStore.orderPizza();

    delete myHawaiiPizza;
    delete myTunaPizza;
    return 0; 
}