李建忠觀察者模式

Table of Contents

1 軟件功能 : 在GUI界面點擊按鍵分割文件,並顯示文件分割的進度條

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 splitter(filePath, number, progressBar);

        splitter.split();
    }
}


class FileSplitter
{
    string m_filePath;
    int m_fileNumber;

    ProgressBar* m_progressBar;

public:
    FileSplitter(const string& filePath, int fileNumber, ProgressBar* progressBar):
        m_filePath(filePath),
        m_fileNumber(fileNumber),
        m_progressBar(progressBar)
    {
    }

    void split()
    {

        //1.讀取大文件

        //2.分批次向小文件中寫入
        for (int i = 0; i < m_fileNumber; i++)
        {
            //...

            //更新進度條
            if (m_progressBar != nullptr){
                m_progressBar->setValue((i + 1) / m_fileNumber);
            }
        }    
    }
};

2 軟件存在的問題 : 違反依賴倒置原則, FileSplitter依賴於 ProgressBar, 即上層依賴於下層, 而下層是容易變化的, 所以要隔離變化

https://www.youtube.com/watch?v=ITU9qLQCaPA&list=PLE0JTxLz7jTR2e8nAyV9vPIqH5NNxlI3N&index=5 : 10:30

3 解決辦法 : 上層與下層均應該依賴於抽象, 而且抽象不能依賴於實現細節

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(filePath, number, this);

        splitter.split();
    }

    virtual void DoProgress(float value)
    {
        progressBar->setValue(value);
    }
}

class IProgress
{
public:
    virtual void DoProgress(float value) = 0;
    virtual ~IProgress(){}
};

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);
            }
        }    
    }
};

 

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