观察者模式

“组件协作”模式:
>现代软件专业分工之后的第一个结果是“框架与应用程序的划分”
“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式。
>典型模式
. Template Method
. Strategy
. Observer/ Event

例:

在一个窗口中添加进度条

普通的做法:

MainForm.cpp

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

FileSplitter.cpp

class FileSplitter
{
    string m_filePath;
    int m_fileNumber;
        //改动
    ProgressBar* m_progressBar;

public:
    FileSplitter(const string& filePath, int fileNumberm, 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 != null)
            {
                m_progressBar->setValue((i + 1) / m_fileNumber);   //更新进度条
            }
        }
    }
};

此方法将出现的问题:

如果出现问题,首先要想到的是八大原则:

该方法首先违背“依赖倒置原则”,该原则为“不要依赖A,而是依赖A的抽象

观察者模式的做法:

MainForm.cpp

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, progressBar);

        splitter.split();
    }

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

FileSplitter.cpp

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

class FileSplitter
{
    string m_filePath;
    int m_fileNumber;
    //ProgressBar* 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);   //更新进度条
            }
        }
    }
};

总结:

使用面向对象的抽象, Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
观察者自己决定是否需要订阅通知,目标对象对此一无所知。
Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分。

 

posted @ 2019-06-20 14:53  追风的小蚂蚁  阅读(201)  评论(0编辑  收藏  举报