设计模式理解:观察者模式

    观察者模式,对象行为型模式,又称为依赖模式,发布订阅模式。当一个对象状态发生改变时,通过通知的形式,让依赖于它的多个对象自动得进行更新。例如JAVA中的Listener ,C#中的Event。 

    在合理的依赖关系中,下层结构不应该依赖于上层结构。但是在某些情况中,需要从底层的方法将上层的对象进行更新。一般的解决方式是将上层的对象以参数的形式不断的传递到底层,而观察者模式中,在底层方法里发出通知到接口中,而上层对象通过对接口的实现,将内容更新至其属性里。

    在案例中,有一个复制大文件时更新进度条进度的 需求。

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

上述的代码设计中,虽然实现了功能,但弊端是显而易见的。

1.下层的FileCopy 依赖于上层 mainform的对象,FileCopy类无法复用于控制台,网页等其他项目工程

2.当需求变为“不用进度条显示进度,改用Label直接以百分比展示进度”,那么自上而下的要把对象类型进行改造,并且progressBar有setvalue方法,而其他控件可能没有。改造起来复杂度高。

3.这个方法当前只能支持一个进度条,如果想要支持多个不同的控件,那就只能要扩展参数,可维护性会变差。

在如下代码中,展示了以观察者模式的模式设计实现相同的需求。摆脱了底层依赖于高层,达到稳定与变化的分离,可以将类和接口原封不动地应用与其他项目。提高的了代码的复用性,易维护性,易扩展性。 以通知地形式,开放通知接口,让应用程序去实现该接口达到更新进度条的目的。

//通知接口
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);
    }
}

猜你喜欢

转载自blog.csdn.net/superSmart_Dong/article/details/114108125