设计模式理解:观察者模式
观察者模式,对象行为型模式,又称为依赖模式,发布订阅模式。当一个对象状态发生改变时,通过通知的形式,让依赖于它的多个对象自动得进行更新。例如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 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);}
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
