(二十二)观察者模式
观察者模式(Observer Pattern)也叫做发布-订阅模式,通过定义一种一对多的依赖关系,被观察者的变动能够及时通知到观察者。通过一种类似消息发布的机制,实现了二者的解耦。
1,观察者模式的设计原则
1,抽象主题(ISubject):定义通知观察者对象的抽象方法;
2,具体主题(ConcreateSubject):具体被观察者;
3,抽象观察者(IObserver):定义响应通知的更新方法;
4,具体观察者(ConcreateObserver):做出响应。
2,简单例子
通过Java API实现V2EX社区简单的订阅功能。
public class V2EX extends Observable {
private String name = "V2EX";
private static V2EX v2EX = null;
private V2EX(){};
public static V2EX getInstance(){
if(null == v2EX){
v2EX = new V2EX();
}
return v2EX;
}
public String getName() {
return name;
}
/**
* 发布消息方法
* @param question 被通知的消息
*/
public void publishQuestion(Question question){
System.out.println(question.getUserName()+"在"+this.name+"上,发出了一个问题。");
// 状态改变
setChanged();
// 通知所有观察者
notifyObservers(question);
}
}
public class Teacher implements Observer {
private String name;
public Teacher(String name){
this.name = name;
}
/**
* 观察者更新的方法
* @param observable observable对象
* @param object 被观察者回传的消息对象
*/
@Override
public void update(Observable observable, Object object){
V2EX v2EX = (V2EX) observable;
Question question = (Question) object;
System.out.println("----------------");
System.out.println(name+"收到了来自:"+question.getUserName()+"的提问:\n"+question.getContent());
}
}
public class Question {
private String userName;
private String content;
//get,set
}
public class Client {
public static void main(String[] args) {
V2EX v2EX = V2EX.getInstance();
Teacher toy = new Teacher("Toy");
Teacher lucy = new Teacher("Lucy");
// 订阅主题
v2EX.addObserver(toy);
v2EX.addObserver(lucy);
// 被观察者消息
Question question = new Question();
question.setUserName("吉米");
question.setContent("如何学习设计模式?");
// 被观察者一旦发布消息,观察者就会接收到消息。
v2EX.publishQuestion(question);
}
}
吉米在V2EX上,发出了一个问题。
----------------
Lucy收到了来自:吉米的提问:
如何学习设计模式?
----------------
Toy收到了来自:吉米的提问:
如何学习设计模式?
3,观察者模式的点评
观察者模式的应用:
- 在消息队列场景中的发布订阅模式,消息在两个系统上下游流转,被观察者状态改变后会通知观察者,并携带一个状态,触发观察者的行为。
- 文件系统使用观察者模式,我们创建一个文件后,会触发文件目录管理器在目录下新增文件,也会触磁盘管理器,缩小空间。
观察者模式和责任链模式的区别:责任链模式时消息在整个系统流转,消息不可变。