设计模式——Observer观察者模式
观察者模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的所有依赖对象。其实就是订阅和发布,只有订阅了才能收到发布的信息。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。观察者模式属于行为型模式。
Servlet中的Listener就是基于观察者模式设计的。
四个角色
抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。
举例
我们假设一种微信公众号的场景,只有你订阅了,才能收到公众号的推送。
Subject.java
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObserver();
}
Observer.java
public interface Observer {
void update(String msg);
}
PublicWeChat.java
实现Subject接口,每次发送推文(更新状态都会调用notifyObserver进行通知)
public class PublicWeChat implements Subject {
private List<Observer>list = new ArrayList<Observer>();
public String getMessage() {
return message;
}
public void setMessage(String message){
this.message = message;
notifyObserver();
}
private String message;
@Override
public void registerObserver(Observer o) {
list.add(o);
}
@Override
public void removeObserver(Observer o) {
list.remove(o);
}
@Override
public void notifyObserver() {
//注意多线程问题,这里简单起见不考虑
for(int i = 0; i < list.size(); i++) {
Observer oserver = list.get(i);
oserver.update(message);
}
}
}
FollowObserver.java
实现Observer接口,当订阅号(被观察者)更新状态时,回调这里的update方法。
public class FollowObserver implements Observer {
private String username;
FollowObserver(Stringusername){
this.username=username;
}
@Override
public void update(String state) {
System.out.println(username+"收到了公众号号发布的消息:"+state);
}
}
测试Main.java
public class Main {
public staticvoid main(String[] args){
PublicWeChat wechat = new PublicWeChat();
Observer user1 =new FollowObserver("用户1");
Observer user2= new FollowObserver("用户2");
Observer user3=new FollowObserver("用户3");
wechat.registerObserver(user1);
wechat.registerObserver(user2);
wechat.registerObserver(user3);
wechat.setMessage("这是一条推送信息!");
}
}
输出:
用户1收到了公众号号发布的消息:这是一条推送信息!
用户2收到了公众号号发布的消息:这是一条推送信息!
用户3收到了公众号号发布的消息:这是一条推送信息!
总结
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。