一、概念
定義一個用於創建對象的接口,讓子類決定實例化哪一個類。Factory Method使得一個類的實例化延遲(目的:解耦,手段:虛函數)到子類。 —《設計模式》Gof
二、動機
在軟件系統中,經常面臨這創建對象的工作;由於需求的變化,需要創建的對象的具體類型經常變化。
如何應對這種變化?如何繞過常規的對象創建方法(new),提供一種“封裝機制”來避免客戶程序和這種“具體對象創建工作”的緊耦合。
三、源代碼講解
class FileSplitter
{
public:
void split(){
//...
}
};
class MainForm : public Form
{
TextBox* txtFilePath; //文件路徑
TextBox* txtFileNumber; //希望分割的個數
ProgressBar* progressBar;
public:
void Button1_Click(){
//收集到用戶輸入的參數信息
string filePath = txtFilePath->getText();
int number = atoi(txtFileNumber->getText().c_str());
//傳遞給FileSplitter,讓該類去分割文件
FileSplitter splitter(filePath, number, progressBar);
//進行分割
splitter.split();
}
};
動態看待問題,上面使用了具體細節類,是靜態特質,定死了,我們應該去判斷業務有沒有需求的變化,是不是隻需要文件分割。比如我們這裏有變化,支持二進制,圖片,視頻,文本分割…,此時我們應該將他聲明爲抽象基類來使用。
四、使用工廠方法模式進行改進
class MainForm : public Form {
SplitterFactory *factory; // 工廠
public:
MainForm(SplitterFactory *factory) {
this->factory = factory;
}
void Button1_Click() {
// 通過虛函數來實現多態new,避免直接使用new創建對象
ISplitter *splitter = factory->CreateSplitter();
splitter->split();
}
};
// 抽象類
class ISplitter {
public:
virtual void split() = 0;
virtual ~ISplitter() { }
};
// 具體類
class BinarySplitter : public ISplitter {
};
class TxtSplitter: public ISplitter {
};
class PictureSplitter: public ISplitter {
};
class VideoSplitter: public ISplitter {
};
// 工廠基類
class SplitterFactory {
public:
virtual ISplitter *CreateSplitter() = 0;
virtual ~SplitterFactory() { }
};
// 具體工廠
class BinarySplitterFactory: public SplitterFactory {
public:
virtual ISplitter* CreateSplitter() {
return new BinarySplitter();
}
};
class TxtSplitterFactory: public SplitterFactory {
public:
virtual ISplitter* CreateSplitter() {
return new TxtSplitter();
}
};
class PictureSplitterFactory: public SplitterFactory {
public:
virtual ISplitter* CreateSplitter() {
return new PictureSplitter();
}
};
class VideoSplitterFactory: public SplitterFactory {
public:
virtual ISplitter* CreateSplitter(){
return new VideoSplitter();
}
};
五、類圖結構
六、要點總結
-
Factory Method 模式用於隔離類對象的使用者和具體類型之間的耦合關係。面對一個經常變化的具體類型,緊耦合關係(new)會導致軟件的脆弱。
-
Factory Method模式通過面向對象的手法(多態),將所要創建的對象工作延遲到子類,從而實現一種擴展(而非更改)的策略,較好地解決了這種緊耦合關係。
-
Factory Method模式解決“單個對象”的需求變化。缺點在於要求創建方法/參數相同。