李建忠工廠方法
Table of Contents
- 1. 創建對象時, 由於需求的變化, 需要創建的對象的具體類型經常變化
- 2. 需求可能發生變化, 造成問題
- 3. 解決辦法 : 面向接口編程, 構造抽象基類
- 4. 對原來用new創建FileSplitter對象的代碼進行修改
- 5. 依然有問題, 違背依賴倒置原則
- 6. 解決方法 : 繞開new操作符, 設計一個虛方法來創建對象, 將依賴延遲到運行時
- 7. 剩餘細節上的處理及總結
1 創建對象時, 由於需求的變化, 需要創建的對象的具體類型經常變化
請先閱讀https://blog.csdn.net/www_minna_com/article/details/104121613
class MainForm : public Form, public IProgress { TextBox* txtFilePath; TextBox* txtFileNumber; ProgressBar* progressBar; public: void Button1_Click() { string filePath = txtFilePath->getText(); int number = atoi(txtFileNumber->getText().c_str()); FileSplitter * splitter = new FileSplitter(filePath, number, this); splitter.split(); } //... }; class FileSplitter { string m_filePath; int m_fileNumber; //ProgressBar* m_progressBar; //具體通知控件 IProgress* m_iprogress; //抽象通知機制 public: FileSplitter(const string& filePath, int fileNumber, Iprogress* iprogress): m_filePath(filePath), m_fileNumber(fileNumber), m_iprogress(iprogress) { } void split() { //1.讀取大文件 //2.分批次向小文件中寫入 for (int i = 0; i < m_fileNumber; i++) { //... //更新進度條 if (m_iprogress != nullptr){ float progressValue = m_fileNumber; progressValue = (i + 1) / progressValue; m_iprogress->DoProgress(progressValue); } } } };
2 需求可能發生變化, 造成問題
https://www.youtube.com/watch?v=0HCQV8mhLR8&list=PLE0JTxLz7jTR2e8nAyV9vPIqH5NNxlI3N&index=8 2:50 FileSplitter變爲TxtSplitter, PictureSplitter, VideoSplitter等等
3 解決辦法 : 面向接口編程, 構造抽象基類
class ISplitter { public: virtual void split() = 0; virtual ~ISplitter(){} }; class TxtSplitter : public ISplitter { //... } class PictureSplitter : public ISplitter { //... } class VideoSplitter : public ISplitter { //... }
4 對原來用new創建FileSplitter對象的代碼進行修改
class MainForm : public Form, public IProgress { TextBox* txtFilePath; TextBox* txtFileNumber; ProgressBar* progressBar; public: void Button1_Click() { string filePath = txtFilePath->getText(); int number = atoi(txtFileNumber->getText().c_str()); ISplitter * splitter = new TxtSplitter(filePath, number, this); //依然有問題, 依賴於具體的TxtSplitter splitter.split(); } //... };
5 依然有問題, 違背依賴倒置原則
https://www.youtube.com/watch?v=0HCQV8mhLR8&list=PLE0JTxLz7jTR2e8nAyV9vPIqH5NNxlI3N&index=8 8:40
6 解決方法 : 繞開new操作符, 設計一個虛方法來創建對象, 將依賴延遲到運行時
https://www.youtube.com/watch?v=0HCQV8mhLR8&list=PLE0JTxLz7jTR2e8nAyV9vPIqH5NNxlI3N&index=8 13:00, 19:00
class SplitterFactory { public: virtual ISplitter* CreateSplitter() = 0; virtual ~SplitterFactory(){} }; class MainForm : public Form, public IProgress { TextBox* txtFilePath; TextBox* txtFileNumber; ProgressBar* progressBar; public: void Button1_Click() { string filePath = txtFilePath->getText(); int number = atoi(txtFileNumber->getText().c_str()); SplitterFactory* factory; ISplitter * splitter = factory->CreateSplitter(); splitter.split(); } //... }; //具體工廠 class TxtSplitterFactory : public SplitterFactory { public: virtual ISplitter* CreateSplitter() { return new TxtSplitter(); } }; class PictureSplitterFactory : public SplitterFactory { public: virtual ISplitter* CreateSplitter() { return new PictureSplitter(); } }; //...
7 剩餘細節上的處理及總結
https://www.youtube.com/watch?v=0HCQV8mhLR8&list=PLE0JTxLz7jTR2e8nAyV9vPIqH5NNxlI3N&index=8 24:30