zoukankan      html  css  js  c++  java
  • 观察者模式

    “组件协作”模式:
    >现代软件专业分工之后的第一个结果是“框架与应用程序的划分”
    “组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式。
    >典型模式
    . 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模式的一个重要组成部分。

  • 相关阅读:
    Pandas学习整理与实践
    数据描述性统计整理
    关于购置硬盘的相关注意点
    福大软工 · 最终作业
    福大软工 · 第十二次作业
    Beta冲刺 (7/7)
    Beta冲刺 (6/7)
    深度剖析Vue中父给子、子给父、兄弟之间传值!
    mysql 增删改插
    前端必学TypeScript之第一弹,st基础类型!
  • 原文地址:https://www.cnblogs.com/zhuifeng-mayi/p/11058726.html
Copyright © 2011-2022 走看看