设计模式-观察者模式(Observer Pattern)
原创
©著作权归作者所有:来自51CTO博客作者ITKaven的原创作品,请联系作者获取转载授权,否则将追究法律责任
推荐:Java设计模式汇总
观察者模式
定义
观察者模式,又被称为发布-订阅(Publish/Subscribe)模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象。
类型
行为型。
角色
- 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
- 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
- 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
- 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
当慕课网的实战课程更新了会通过APP、微信通知购买课程的用户,这便是一种观察者模式的实际应用。
例子
当有用户向某个实战课程提问了,该实战课程的讲师就会收到该提问,以便回答。
这里我们为了简化,不自己写具体业务,借用Java中的Observable类
、Observer接口
。
Question类,用户提问的问题类。
package com.kaven.design.pattern.behavioral.observer;
public class Question {
private String userName;
private String questionContent;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getQuestionContent() {
return questionContent;
}
public void setQuestionContent(String questionContent) {
this.questionContent = questionContent;
}
}
Course类(具体主题角色),这里不自己实现具体主题角色的功能,通过继承Observable类
,便可以很方便的实现这些功能,其实实现这些功能也不难,但要做到高性能、线程安全也有一定难度,大家可以构思一下怎么实现。
package com.kaven.design.pattern.behavioral.observer;
import java.util.Observable;
public class Course extends Observable {
private String courseName;
public Course(String courseName) {
this.courseName = courseName;
}
public String getCourseName() {
return courseName;
}
public void produceQuestion(Course course , Question question){
System.out.println(question.getUserName()+"在"+course.courseName+"提交了问题");
setChanged();
notifyObservers(question);
}
}
Teacher类(具体观察者角色),为了方便,也是通过实现Observer接口
来简化实现具体观察者角色的功能。
package com.kaven.design.pattern.behavioral.observer;
import java.util.Observable;
import java.util.Observer;
public class Teacher implements Observer {
private String teacherName;
public Teacher(String teacherName) {
this.teacherName = teacherName;
}
public void update(Observable o, Object arg) {
Course course = (Course) o;
Question question = (Question) arg;
System.out.println(teacherName+"老师的"+course.getCourseName()+"课程接收到-"+question.getUserName()+"提交的问答:"+question.getQuestionContent());
}
}
应用层代码:
package com.kaven.design.pattern.behavioral.observer;
public class Test {
public static void main(String[] args) {
Course course = new Course("Java设计模式");
Teacher teacher1 = new Teacher("Kaven");
Teacher teacher2 = new Teacher("yy");
course.addObserver(teacher1);
course.addObserver(teacher2);
//业务逻辑
Question question = new Question();
question.setUserName("Jack");
question.setQuestionContent("观察者模式如何实现?");
course.produceQuestion(course , question);
}
}
输出:
Jack在Java设计模式提交了问题
yy老师的Java设计模式课程接收到-Jack提交的问答:观察者模式如何实现?
Kaven老师的Java设计模式课程接收到-Jack提交的问答:观察者模式如何实现?
这里便完成了一个简单的观察者模式的例子,大家可以去看看Observable类
、Observer接口
的源码,理解内部是怎么实现的。
适用场景
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
优点
- 观察者和被观察者是抽象耦合的。
- 建立了一套触发机制。
缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
如果有说错的地方,请大家不吝赐教(记得留言哦~~~~)。