前言23设计模式速记单例模式工厂方法模式抽象工厂模式Builder/Builder模式原型模式享元模式、门面模式、适配器模式、装饰器模式持续更新中..快速记忆的23种设计模式请看上面第一篇文章,本文将带你了解观察者模式。模式定义定义了对象之间的一对多依赖关系,允许多个观察者对象同时监视一个主题对象。当主题对象发生变化时,它的所有依赖者都会得到通知和更新。这种模式有时也称为发布-订阅模式、模型-视图模式,是一种对象行为模式。观察者模式是对象之间一对多的模式。依赖对象是Subject,依赖对象是Observer。Subject将更改通知Observer。Subject为1,Observer为多个。要解决的问题是一个对象状态改变通知其他对象的问题,需要考虑易用性和低耦合性,保证高度协作。模式构成示例描述示例概述一天下午,班主任通知学生和某班的老师他们将上一节课,以便对老师的教学质量进行评分。师生收到后开始安排相关课程;上课时,老师和班主任可以通过观察学生的表情来判断课程的好坏。教师观察学生皱眉可以适当调节课程气氛。班主任观察到同学们的课堂气氛有所好转,高分课程结束后,班主任和老师一起回到办公室,共同回顾这门快乐的课程。第一步:构建课程实体类classCourse{//上课时间:timeprivateDatetime;//上课地点:placeprivateStringplace;//上课内容:contentprivateStringcontent;//省略get/set...publicCourse(){}publicCourse(Datetime,Stringplace,Stringcontent){this.time=time;this.place=place;this.content=content;}}第二步:构造一个discoverer抽象类和相关实现类,分别被teacher和classteacher继承接口并重写相关方法abstractclassObserver{abstractvoidupdate(Objectargs);publicObserver(Stringidentity){this.identity=identity;}privateStringidentity;publicStringgetIdentity(){returnidentity;}publicvoidsetIdentity(Stringidentity){this.identity=identity;}}第三步:创建一个特定的观察员角色,老师带着教材开始上课/***教师班级*-观察员之一*-观察学生上课情况*/classTeacherObserverextendsObserver{privateCoursecourse;@Overridepublicvoidupdate(Objectargs){DateFormatdf=DateFormat.getTimeInstance(DateFormat.LONG,Locale.CHINA);System.out.println("我是王老师,讲课...");course=newCourse(newDate(),"A楼","高等数学");System.out.println("今天上课时间:"+df.format(course.getTime())+"地点:"+course.getPlace()+"课堂内容:"+course.getContent());}publicTeacherObserver(Stringidentity){super(identity);}}第四步:创建具体观察员角色,班主任会来听课/***班主任会来听课*-观察员之一*-观察学生上课状态*/classHeadTeacherObserverextendsObserver{@Overridepublicvoidupdate(Objectargs){System.out.println("我是班主任,我正在检查课程的质量...");System.out.println("学生反馈课程质量为:"+args);}publicHeadTeacherObserver(Stringidentity){super(identity);}}第五步:创建observer/***subject类的抽象subject角色*-模拟被观察者subject*/abstractclassSubject{/***修改通知*/abstractvoiddoNotify();/***添加观察者*/abstractvoidaddObservable(Observero);/***移除观察者*/abstractvoidremoveObservable(Observero);}步骤6:创建一个具体角色的学科对象,学生的主体就是学科主体/***StudentSubject*-观察主体*/classStudentSubjectextendsSubject{/***classstate*/privateStringstate;publicStringgetState(){返回状态;}publicvoidsetState(Stringstate){this.state=state;}privateListobservableList=newArrayList<>();@OverridepublicvoiddoNotify(){for(Observerobserver:observableList){observer.update(state);}}@OverridepublicvoidaddObservable(Observerobservable){observableList.add(observable);}@OverridepublicvoidremoveObservable(Observerobservable){try{if(observable==null){thrownewException("要移除的observable不能为空");}else{if(observableList.contains(observable)){System.out.println("下课了,"+observable.getIdentity()+"我回办公室了");observableList.remove(observable);}}}catch(Exceptione){e.printStackTrace();}}}第七步:开始上课,开始记录报告//创建观察者教师TeacherObserverteacherObversable=newTeacherObserver("王老师");//创建观察者班主任HeadTeacherObserverheadTeacherObserver=newHeadTeacherObserver("班主任");//学生反映班级状态studentSubject.setState("讲的很好,很好!");studentSubject.addObservable(teacherObversable);studentSubject.addObservable(headTeacherObserver);//开始上课studentSubject.doNotify();//下课studentSubject.removeObservable(headTeacherObserver);studentSsubject.removeObservable(teacherObversable);}}输出结果我是王老师,我正在讲课...今天上课时间:11:57:01pm地点:A楼上课内容:高等数学我是班主任听课,查课程质量...学员反映的课程质量是:讲的好,很好!下课了,班主任已经回办公室下课了,王老师也回到了办公室。两者之间的耦合关系是一种抽象的耦合关系;在目标和观察者之间建立了一套触发机制。缺点是目标和观察者之间的依赖关系没有完全解决,可能会出现循环引用;当观察到的目标对象较多时,通知的释放会耗费大量的时间,影响程序的运行效率。应用场景当改变一个对象的状态可能需要改变其他对象时使用观察者模式,而实际的一组对象事先并不知道或动态变化。注:1.JAVA已经有观察者模式的支持类。2.避免循环引用。3.如果是顺序执行,一定的观察者错误会导致系统卡住,一般采用异步的方式。源码中应用#JDK:java.util.Observable#Spring:org.springframework.context.ApplicationListenerObservable源码分析Observable接口publicinterfaceObserver{voidupdate(Observableo,Objectarg);}Observable类publicclassObservable{privateVectorobs;//添加observationpublicsynchronizedvoidaddObserver(Observero){if(o==null)thrownewNullPointerException();if(!obs.contains(o)){obs.addElement(o);}}//删除观察者publicsynchronizedvoiddeleteObserver(Observero){obs.removeElement(o);}//通知所有观察者publicvoidnotifyObservers(){notifyObservers(null);}publicvoidnotifyObservers(Objectarg){/**atemporaryarraybuffer,usedasasnapshotofthestateof*currentObservers.*/Object[]arrLocal;synchronized(this){/*我们不希望观察者在保持自己的监视器的同时对*任意代码进行回调。*我们从*向量中提取每个Observable并存储观察者状态的代码*需要同步,但通知观察者*不需要(不应该)。issa*notificationinprogress*2)arecentlyunregisteredObserverwillbe*wronglynotifiedwhenitdoes'tcare*/if(!changed)return;arrLocal=obs.toArray();clearChanged();}for(inti=arrLocal.length-1;i>=0;i--)((Observer)arrLocal[i]).update(this,arg);}}使用JDK提供的类实现观察者模式通过使用JDK类实现上述实例相关的观察模式,构建-inobserver类有Observer接口和Observable类。使用这两个类中的方法可以很好的完成观察者模式,并且JDK已经为我们做了相关的加锁操作来保证线程安全。总体来说,有助于我们对上面的例子进行改进和简化,代码如下:packagecom.niuh.designpattern.observer.v2;importjava.text.DateFormat;importjava.util.Date;importjava.util。语言环境;importjava.util.Observable;importjava.util.Observer;/***观察者模式*/publicclassObserverPattern{//第六步:开始上课,开始记录报告publicstaticvoidmain(String[]args){//创建学生主题StudentSubjectstudentSubject=newStudentSubject();//创建观察者老师TeacherObserverteacherObversable=newTeacherObserver();//创建一个观察员班主任HeadTeacherObserverheadTeacherObserver=newHeadTeacherObserver();//学生反映班级状态studentSubject.setState("讲得好,很好!");studentSubject.addObserver(teacherObversable);学生主题.addObserver(headTeacherObserver);//开始上课studentSubject.doNotify();//下课studentSubject.deleteObserver(headTeacherObserver);studentSubject.deleteObserver(teacherObversable);}}/***课程class*/classCourse{//上课时间:timeprivateDatetime;//类所在:placeprivateStringplace;//类内容:contentprivateStringcontent;publicDategetTime(){returntime;}publicvoidsetTime(Datetime){this.time=time;}publicStringgetPlace(){returnplace;}publicvoidsetPlace(Stringplace){this.place=place;}publicStringgetContent(){returncontent;}publicvoidsetContent(Stringcontent){this.content=content;}publicCourse(){}publicCourse(Datetime,Stringplace,Stringcontent){this.time=time;this.place=place;this.content=content;}}/***教师班*-观察员之一*——观察学生上课情况*/classTeacherObserverimplementsObserver{privateCoursecourse;@Overridepublicvoidupdate(Observableo,Objectarg){DateFormatdf=DateFormat.getTimeInstance(DateFormat.LONG,Locale.CHINA);System.out.println("我是王老师,我在讲课...");course=newCourse(newDate(),"教学楼","高等数学");System.out.println("今天上课时间:"+df.format(course.getTime())+"地点:"+course.getPlace()+"上课内容:"+course.getContent());}}/***班主任来听课*-观察员之一*-观察学生上课情况*/classHeadTeacherObserverimplementsObserver{@Overridepublicvoidupdate(Observableo,Objectarg){System.out.println("我是班主任在这里听课,检查课程质量...");System.out.println("学生反馈课程质量为:"+arg);}}/***Studentsubject*-要观察的对象*/classStudentSubjectextendsObservable{/***Classstatus*/privateStringstate;publicStringgetState(){returnstate;}publicvoidsetState(Stringstate){this.state=state;}publicvoiddoNotify(){//Setflagthis.setChanged();//通知观察者做出反应Actionthis.notifyObservers(state);}}输出结果:我是班主任,正在检查课程质量...学员对课程质量的反馈是:讲的好,很好!我是王老师,我正在讲课……今日上课时间:12:04:27地点:教学楼A上课内容:高等数学PS:以上代码提交在Github上:https://github.com/Niuh-Study/niuh-designpatterns.git