当前位置:文档之家› 基于观察者模式的系统设计与实现

基于观察者模式的系统设计与实现

基于观察者模式的系统设计与实现【摘要】:本论文的论述中心是要对观察者模式进行研究和分析,我主要是首先通过对观察者模式简介和概述,一定程度上了解观察者模式,再者,对观察者模式结构的分析与使用方法以及通过研究观察者优缺点,深入对整一个观察者模式进行透彻的分析。

通过各种实例,一一地对其仔细的运用。

【关键字】:观察者模式主题 Observable类观察者接口调用【正文】:1.1观察者模式的基本简介:1.1.1 观察者模式观察者模式(有时又被称为发布/订阅模式)是软体设计模式的一种。

在这种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。

这通常透过呼叫各个观察者所提供的方法来实现。

此种模式通常被用来实作事件处理系统。

同时观察者模式(Observer)完美的将观察者和被观察的对象分离开。

举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。

面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。

一个对象只做一件事情,并且将他做好。

观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。

1.1.2 实现方式观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。

在刚才的例子中,业务数据是被观察对象,用户界面是观察者。

观察者和被观察者之间存在“观察”的逻辑关联,当被观察者发生改变的时候,观察者就会观察到这样的变化,并且做出相应的响应。

如果在用户界面、业务数据之间使用这样的观察过程,可以确保界面和数据之间划清界限,假定应用程序的需求发生变化,需要修改界面的表现,只需要重新构建一个用户界面,业务数据不需要发生变化。

实现观察者模式的时候要注意,观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,从根本上违反面向对象的设计的原则。

无论是观察者“观察”观察对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。

1.2 “主题”与“观察者”在许多设计中,经常设计多个对象都对一个特殊对象中的数据变化感兴趣,而且这多个对象都希望跟踪那个特殊对象中的数据变化。

例如,某些寻找工作的人对“求职中心”的职业需要的变化非常关心,很想跟踪“求职中心”中职业需要信息的变化。

一位想知道“求职中心”职业需求信息变化的人需要成为求职中心的“求职者”,即让求职中心把自己登记到求职中心列表中,当一个人成为求职中心后的求职者之后,求职中心就会及时通知他最新的职业需求信息。

如果一个求职者不想继续知道求职中心的职业需求信息,就让求职中心把自己从求职中心的求职者列表中删除,求职中心就不会再通知他职业需求信息。

观察者模式是关于多个对象想知道一个对象中数据变化情况的一种成熟的模式。

观察者模式中有一个称作“主题”的对象和若干个称作“观察者”的对象,“主题”和“观察者”间是一种一对多的依赖关系,当“主题”的状态发生变化时,所有“观察者”都得到通知。

前面所述的“求职中心”相当于观察者模式的一个具体“主题”;每一个“求职者”相当于观察者模式中的一个具体“观察者”。

1.3模式的结构与使用观察者模式的结构中包括四种角色。

•主题(subject):主题是一个接口,该接口规定了具体主题需要实现的方法,比如,添加、删除观察者以及通知观察者更新数据的方法。

•观察者(Observer):观察者是一个接口,该接口规定了具体观察者用来更新数据的方法。

•具体主题(ConcreteSubject):具体主题是实现主题接口类的一个实例,该实例包含有可以经常发生变化的数据。

具体主题需使用一个集合,比如ArrayList,存放观察者的引用,以便数据变化时通知具体观察着。

•具体观察者(ConcreteObserver):具体观察者是实现观察者接口类得一个实例。

具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,使自己成为它的观察者,或让这个具体主题将自己从具体主题的集合中删除,使自己不再是它的观察者。

1.3.1 结构的描述下面通过一个简单的问题来描述观察者模式中所涉及的各个角色,这个简单的问题是:有一个大学毕业和一个归国留学着都希望能及时知道“求职中心”最新的职业需求信息。

1.主题本问题中,主题接口Subject规定的了具体主题需要实现的添加、删除观察者以及通知观察者更新数据的方法。

Subject接口的代码如下:Subject.javaPublic interface Subject{Public void addObserver(Observer o);Public void deleteObserver(Observer o);}2.观察者观察者是一个接口,该接口规定了具体观察者用来更新数据的方法。

对于本问题,观察者接口规定的方法是;hearTelephone()(相当于观察者模式类图中的update()方法),即要求具体观察者都通知实现hearTelephone()方法(模拟接听电话)来更新数据。

Observer接口的代码如下:Observer.javaPublic interface Observer{Public void hearTelephone(String hearMess);}3.具体主题主题接口规定了具体主题需要实现的通知观察者更新数据的notifyObservers()方法,具体主题通过实现notifyObserver()方法来通过具体观察者,实现的方式是遍历具体主题中用来存放观察者引用的集合,并让集合中的每个具体观察者接口(Observer)规定更新数据的方法,比如heaeTelephone()方法。

对于某种问题,集体主题应当保证数据确实发生了变化再遍历存放观察者应用的集合。

在本问题中,具体主题维护着一个String字符串,用来表示“求职中心”的职业需求信息,当该String字符串发生变化时,具体主题遍历存放观察者引用的集合。

创建具体主题的类是SeekJobCenter,代码如下:SeekJobCenter.javaimport java.util.ArrayList;Public class SeekJobCenter implements Subject{String mess;Boolean changed;ArrayList<Observer> personList;SeekJobCenter(){personList = new ArrayList<Observer>();mess = “ ”;changed = new false;}Public void addObserver(Observer o){if(!(personList.contains(o)))personList.add(o);}Public void deleteObserver(Observer o){if(personList.contains(o))personList.remove(o);}{if(changed){For(int i = 0 ;i<personList.size();i++){Observer observer = personList.get(i);Observer.hearTelephone(mess);}changed = false;}}Public void giveNewMess(String str){if(str.equals(mess))changed = false;else{mess = str;changed = true;}}}3.具体观察者本问题中,实现观察者接口Observer的类有两个:一个是UniversityStudent类,另一个是HaiGui。

UniversityStude类的实例调用hearTelephone(String heardMess)方法时,会将参数引用的字符串保存到一个文件中。

HaiGui类的实例调用hearTelephone(String heardMess)方法时,如果参数引用的字符串中包含有“程序员”或“软件”,就将信息保存到一个文件中。

UniversityStudent和HaiGui类的代码如下:UniversityStudent.javaimport java.io.*;public class UniversityStudent implements Observer observer{Subject subject;File myFile;UniversityStudent(Subject subject,String flieName){this.subject = subject;subject.addObserver(this);myFile = new File(fileName);}public void hearTelephone(String heardMess){Try{RandomAccessFile out = new RandomAccessFile(myFile,”rw”);out.seek(out.length());byte [] b = heardMess.getBytes();out.write(b);System.out.print(“我是一个大学生,”);System.out.println(“我向文件”+ myFile.getName() + “写入如下内容:”);System.out.println(heardMess);}catch(IOException exp){System.out.println(exp.toString());}}}HaiGui.javaimport java.io.*;import java.util.regex.*;public class HaiGui implements Observer{Subject subject;File myFile;HaiGui(Subject subject,String fileName){this.subject = subject;subject.addObserver(this);myFile =new File(fileName);}public void hearTelephone(String heardMess){Try{boolean boo = heardMess.contains(“ja va 程序员”)||heardMess.contains(“软件”);if(boo){RandomAccessFile out = new RandomAccessFile(myFile,”rw”);out.seek(out.length());byte [] b = heardMess.getBytes();out.write(b);System.out.print(“我是一个海归,”);System.out.println(“我向文件”+ myFile.getName()+”写入如下内容:”);System.out.println(heardMess);}else{System.out.println(“我是海归,这次的信息中没有我需要的信息”);}}catch(IOException exp){System.out.println(exp.toString());}}}1.3.3 模式的使用前面已经使用观察者模式给出了可以使用的类,这些类就是一个小框架,可以使用这个小框架中的类编写应用程序。

相关主题