close

 簡單工廠模式 ( Simple Factory Pattern )

 

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

假設,有一間披薩店在裡面賣各式各樣的Pizza,如果有人點了夏威夷口味的披薩,我們就準備夏威夷的披薩,然後送入烤箱→拿給消費者。

 




#include 
#include 
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 * orderPizza 的意思是指:
		返回一個Pizza的指針
	*/
	Pizza *ret = NULL;
	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 
#include 
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 
#include 
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; 
}
​​​​​​​

 

 

 

 

arrow
arrow
    創作者介紹
    創作者 Eric 的頭像
    Eric

    一個小小工程師的心情抒發天地

    Eric 發表在 痞客邦 留言(0) 人氣()