Design pattern understanding: the observer pattern

    Observer model, object behavior model, also known as dependency model, publish-subscribe model. When the state of an object changes, multiple objects that depend on it can be automatically updated through notifications. For example, Listener in JAVA, Event in C#. 

    In a reasonable dependency relationship, the lower structure should not depend on the upper structure . However, in some cases, the upper-layer objects need to be updated from the bottom-layer method. The general solution is to continuously pass the upper-layer objects to the bottom layer in the form of parameters. In the observer mode, notifications are sent to the interface in the bottom-layer method, and the upper-layer object updates the content to its attributes through the implementation of the interface. in.

    In the case, there is a need to update the progress bar when copying large files.

class FileCopy{
   string srcpath;
   string dispath;
   ProgressBar * progressBar;
   public:
   FileCopy(string s,string d,ProgressBar & p):filepath(s),dispath(d),progressBar(p){}
   void copy(){
     //1 创建目标文件,读取源文件
     disfile =createfile(dispath)
     srcfile =readfile(srcpath)
     
     ....
     double totalsize = srcfile.totalsize();
     double sum = 0;
     while(content=srcfile.readline()){
        //按行写入文件
        disfile.write(content);
        //写文件后更新进度条
        sum +=content.size;
        progressBar->setvalue(sum/totalsize);
     }
   }
}

//------------界面---------------
class MainForm {
ProgressBar  bar;
public:
 void button_Click(){ 
    //.....
    FileCopy fc(srcfile,disfile,&bar);
    fc.copy();
 }
}

In the above code design, although the function is realized, the drawbacks are obvious.

1. The FileCopy of the lower layer depends on the object of the upper mainform, and the FileCopy class cannot be reused for other projects such as consoles, web pages, etc.

2. When the requirement becomes "not use the progress bar to display the progress, use Label to display the progress directly in percentage", then the object type should be modified from top to bottom, and the progressBar has a setvalue method, while other controls may not. The transformation is highly complex.

3. This method currently only supports one progress bar. If you want to support multiple different controls, you can only extend the parameters, and the maintainability will be worse.

In the following code, it is shown that the pattern design of the observer pattern realizes the same requirement. Get rid of the dependence of the bottom layer on the top layer, and achieve the separation of stability and change, and classes and interfaces can be used intact with other projects. Improved code reusability, easy maintenance, and easy scalability. In the form of notification, the notification interface is opened, allowing applications to implement the interface to achieve the purpose of updating the progress bar.

//通知接口
class INotice{
    virtual void notify(double)=0;
}
class FileCopy{
   string srcpath;
   string dispath;
   vector<INotice*> notices; //通知对象集合
   public:
   FileCopy(string s,string d):filepath(s),dispath(d){}
   void add(INotice * in){notices.push_back(in);}
   void copy(){
     //1 创建目标文件,读取源文件
     disfile =createfile(dispath)
     srcfile =readfile(srcpath)
     
     ....
     double totalsize = srcfile.totalsize();
     double sum = 0;
     while(content=srcfile.readline()){
        //按行写入文件
        disfile.write(content);
        //写文件后更新进度条
        sum +=content.size;
        //给所有依赖发出通知
        copynotify(sum/totalsize);
     }
   }
   protected:
   void copynotify(double value){
      for(notice :notices){
        notice->notify(value);
      }
   }
}

//------------界面,实现INotice接口方法---------------
class MainForm:public INotice{
ProgressBar  bar;
public:
 void button_Click(){ 
    //.....
    ChildForm *cform = new ChildForm ();
    FileCopy fc(srcfile,disfile);
    
    fc.add(this);
    fc.add(cform );
    fc.copy();
 }
 virtual void notify(double value){
   bar.setvalue(value);
 }
}

class ChildForm:public INotice{
    Label   label;
    virtual void notify(double value){
       bar.settitle(value);
    }
}

 

 

Guess you like

Origin blog.csdn.net/superSmart_Dong/article/details/114108125