簡單工廠模式的核心思想是把創建對象過程和對象本身業務處理分離,工廠處理創建對象的細節。
具體實現如下:
1. 定義一個操作接口:
class COperation
{
public:
virtual double GetResult(double a, double b) = 0;
};
2. 定義具體的操作類:
class COperationAdd : public COperation
{
public:
virtual double GetResult(double a, double b)
{
return a+b;
}
};
class COperationSub : public COperation
{
public:
virtual double GetResult(double a, double b)
{
return a-b;
}
};
3. 定義簡單工廠類:
class CSimpleOperationFactory
{
public:
virtual COperation* createOperation(int type)
{
COperation* op = NULL;
switch(type)
{
case 1:
{
op = new COperationAdd();
}
break;
case 2:
{
op = new COperationSub();
}
break;
default:
break;
}
return op;
}
};
//靜態方法
class CSimpleOperationFactory
{
public:
static COperation* createOperation(int type)
{
COperation* op = NULL;
switch(type)
{
case 1:
{
op = new COperationAdd();
}
break;
case 2:
{
op = new COperationSub();
}
break;
default:
break;
}
return op;
}
};
4. 用戶端代碼:
class calculator
{
public:
calculator(CSimpleOperationFactory* factory)
{
mFactory = factory;
}
double operate(double a, double b, int type)
{
COperation* op = mFactory->createOperation(type);
return op->GetResult(a, b);
}
private:
CSimpleOperationFactory* mFactory;
};
我們無需提供具體的子類類名,只需要提供一個類型(type)即可得到相應的實例對象。這樣的話,當子類的類名更換或者增加子類時我們都無需修改客戶端代碼,只需要在簡單工廠類上增加一個分支判斷代碼即可。
缺點:
該模式使得工廠的負擔過重,而且每次添加新產品,都需要修改工廠,不是很符合開閉原則,但是比直接在業務邏輯裏添加要好很多了。
問:這麼做有什麼好處?似乎只是把問題搬到另一個對象罷了,問題依然存在。
答:別忘了,SimpleFactory可以有許多客戶。所以把創建對象的代碼封裝進一個類,當以後實現改變時,只需要修改這個類即可。別忘了,我們也正要把具體實例化的過程,從客戶的代碼中刪除!
問:我曾看過一個類似的實現,把工廠定義成一個靜態的方法。這有何差別?
答:利用靜態方法實現一個簡單工廠,這是很常見的技巧,常被稱爲靜態工廠。爲何使用靜態方法?因爲不需要使用創建對象的方法來實例化對象。但請記住,這也有缺點,不能通過繼承來改變創建方法的行爲。