李建忠工廠方法

李建忠工廠方法

Table of Contents

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章