Java设计模式-观察者模式(行为型)
观察者模式(Observer Pattern)是一种行为设计模式目的是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都能得到通知并自动更新。其核心思想是将被观察的对象(主题,Subject)和观察它的对象(观察者,Observer)分离,使得它们可以独立地改变和复用。主题维护一个观察者列表,当主题状态改变时,通过调用观察者的更新方法来通知它们,实现了低耦合的事件通
·
Java设计模式:观察者模式
观察者模式简介
观察者模式(Observer Pattern)是一种行为设计模式,目的是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都能得到通知并自动更新。其核心思想是将被观察的对象(主题,Subject)和观察它的对象(观察者,Observer)分离,使得它们可以独立地改变和复用 。主题维护一个观察者列表,当主题状态改变时,通过调用观察者的更新方法来通知它们,实现了低耦合的事件通知机制。
通过一个简单的问题来描述观察者模式中所涉及的各个角色。一个大学生和一个归国留学生都希望及时知道“求职中心”最新的职位需求信息。
类图

- 主题
主题是Subject接口,该接口规定了具体主题需要实现的添加观察者、删除观察者以及发送数据给观察者的方法。代码如下:
public interface Subject{
public void addObserver(Observer o);
public void deleteObserver(Observer o);
public void notifyObservers(String str);
}
- 观察者
观察者是Observer接口。该接口规定了具体观察者用来更新数据的方法。对于本问题,观察者接口规定的方法是hearTelephone(相当于观察者模式类图中的update方法),即要求具体观察者通过实现hearTelephone方法(模拟接听电话)来更新数据。Observer接口的代码如下:
public interface Observer{
public void hearTelephone(String heardMess);
}
- 具体主题
具体主题是SeekJobCenter类。具体主题通过实现notifyObservers方法来通知具体观察者,实现的方式是遍历具体主题中用来存放观察者的集合,并让集合中的每个具体观察者执行观察者接口(Observer)规定更新数据的方法,例如hearTelephone方法。SeekJobCenter类的代码如下:
import java.util.ArrayList;
public class SeekJobCenter implements Subject{
ArrayList<Observer> personList; //存放观察者对象的数组表
public SeekJobCenter(){
personList = new ArrayList<Observer>();
}
public void addObserver(Observer observer){
if(!(personList.contains(observer)))
personList.add(observer); //把观察者对象添加到数组表
}
public void deleteObserver(Observer observer){
if(personList.contains(observer))
personList.remove(observer);
}
public void notifyObservers(String mess){ //通知所有的观察者
for(int i = 0; i < personList.size(); i++){
Observer observer = personList.get(i);
observer.hearTelephone(mess); //让观察者接听电话
}
}
}
- 具体观察者
具体观察者是Student类和HaiGui类。Student类的实例调用hearTelephone(String heardMess)方法时,会将收到的数据保存到一个文件中。HaiGui类的实例调用hearTelephone(String heardMess)方法时,如果数据中包含“程序员”或“软件”等字样,就将信息保存到一个文件中。Student类代码:
import java.io.*;
public class Student implements Observer{
Subject subject;
File myFile;
public Student(Subject subject, String fileName){
this.subject = subject;
subject.addObserver(this); //使当前对象成为 subject 具体主题的观察者
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 类代码:
import java.io.*;
public class HaiGui implements Observer{
Subject subject;
File myFile;
public HaiGui(Subject subject, String fileName){
this.subject = subject;
subject.addObserver(this); //使当前对象成为 subject 具体主题的观察者
myFile = new File(fileName);
}
public void hearTelephone(String heardMess){
try{
boolean isOK = heardMess.contains("Java程序员") || heardMess.contains("软件");
RandomAccessFile out = new RandomAccessFile(myFile, "rw");
if(isOK){
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());
}
}
}
应用程序 Application.java 使用了上述类,演示一个大学生和一个归国留学生成为求职中心的观察者;当求职中心有新的人才需求信息时,大学生和归国留学生将得到通知。
public class Application{
public static void main(String args[]){
Subject center = new SeekJobCenter(); //具体主题
Observer zhang = new Student(center, "A.txt"); //具体观察者
Observer wang = new HaiGui(center, "B.txt"); //具体观察者
center.notifyObservers("星星公司需要20个Java程序员."); //主题通知信息
center.notifyObservers("月月公司需要8个动画设计师.");
center.notifyObservers("星月公司需要9个电工.");
}
}
运行结果:
我是一个大学生,我向文件A.txt写入如下内容:
星星公司需要20个Java程序员。
我是一个海归,我向文件B.txt写入如下内容:
星星公司需要20个Java程序员。
我是一个大学生,我向文件A.txt写入如下内容:
月月公司需要8个动画设计师。
我是一个大学生,我向文件A.txt写入如下内容:
星月公司需要9个电工。
上述代码对应的类图puml代码
@startuml
interface Subject {
+addObserver(Observer o)
+deleteObserver(Observer o)
+notifyObservers(String str)
}
interface Observer {
+hearTelephone(String heardMess)
}
class SeekJobCenter {
-ArrayList<Observer> personList
+SeekJobCenter()
+addObserver(Observer observer)
+deleteObserver(Observer observer)
+notifyObservers(String mess)
}
class Student {
-Subject subject
-File myFile
+Student(Subject subject, String fileName)
+hearTelephone(String heardMess)
}
class HaiGui {
-Subject subject
-File myFile
+HaiGui(Subject subject, String fileName)
+hearTelephone(String heardMess)
}
class Application {
+main(String args[])
}
Subject <|.. SeekJobCenter
Observer <|.. Student
Observer <|.. HaiGui
SeekJobCenter --> Observer : personList
Student --> Subject : subject
HaiGui --> Subject : subject
@enduml
上述puml代码中:
- 定义了
Subject接口,包含添加观察者、删除观察者和通知观察者的方法。 Observer接口定义了接收通知更新数据的hearTelephone方法。SeekJobCenter类实现了Subject接口,维护观察者列表并实现相关通知方法。Student和HaiGui类实现了Observer接口,各自有处理通知数据的逻辑。Application类是程序入口,用于测试和演示整个观察者模式的运行。类之间的关系通过箭头表示,体现了实现、关联等关系。
更多推荐
所有评论(0)