什么是观察者模式
它定义对象间的一种一对多的依赖关系,可以在一个对象的状态/事件发生改变时,通知多个 “观察” 该对象的其他对象。
这个应该很好理解,就像订阅机制一样。当订阅的内容更新后,会推送给所有订阅者了。
注:观察者模式是一种行为模式(这类模式负责对象间的高效沟通和职责委派。)。
主要角色
抽象主题(Subject):也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
具体主题(Concrete Subject):也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
抽象观察者(Observer):它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
具体观察者(Concrete Observer):实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
注:java中已提供相关支持类,java.util.Observable 和 java.util.Observer。
Observable相关于抽象目标(Subject)的功能,Observer就是抽象观察者。查看下面的示例,再看下这两个类的源码就能很清楚。
优缺点
优点
降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
目标与观察者之间建立了一套触发机制。
缺点
当目标有很多直接或间接观察者时,通知所有观察者会花费很多时间,影响程序的效率。
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用(目标与观察者之间的依赖关系并没有完全解除),可能导致系统崩溃。
实例demo
目标即被观察者:保存所有观察者,当变化发生后通知所有观察者。
//抽象目标类
public abstract class Subscription {
protected List<Subscriber> subscribers = new ArrayList<Subscriber>();
public void addSubscriber(Subscriber subscriber) {
subscribers.add(subscriber);
}
public void deleSubscriber(Subscriber subscriber) {
subscribers.remove(subscriber);
}
public abstract void subscriptionUpdate(String content);
}
//具体目标类
public class SubscriptionBlog extends Subscription {
@Override
public void subscriptionUpdate(String content) {
for (Subscriber subscriber : subscribers) {
subscriber.receiveNotification(content);
}
}
}
观察者:获得目标变化的通知,并处理。
//抽象观察者
public interface Subscriber {
void receiveNotification(String notification);
}
//3个具体观察者
public class Subscriber1 implements Subscriber {
@Override
public void receiveNotification(String notification) {
System.out.println("Subscriber1 收到通知:"+notification);
}
}
public class Subscriber2 implements Subscriber {
@Override
public void receiveNotification(String notification) {
System.out.println("Subscriber2 收到通知:"+notification);
}
}
public class Subscriber3 implements Subscriber {
@Override
public void receiveNotification(String notification) {
System.out.println("Subscriber3 收到通知:"+notification);
}
}
客户端调用:这里目标有3次变化,每次变化观察者也是变化的,可以注意下。
public class ObserverTest {
public static void main(String[] args) {
Subscription subscription = new SubscriptionBlog();
Subscriber subscriber1 = new Subscriber1();
Subscriber subscriber2 = new Subscriber2();
Subscriber subscriber3 = new Subscriber3();
subscription.addSubscriber(subscriber1);
subscription.addSubscriber(subscriber2);
System.out.println("-----目标变化-----");
subscription.subscriptionUpdate("xxx新增了一篇博客A。");
System.out.println();
subscription.addSubscriber(subscriber3);
System.out.println("-----目标变化-----");
subscription.subscriptionUpdate("xxx更新了一篇博客A。");
System.out.println();
subscription.deleSubscriber(subscriber2);
System.out.println("-----目标变化-----");
subscription.subscriptionUpdate("xxx新增了一篇博客B。");
}
}
实例结果:
-----目标变化-----
Subscriber1 收到通知:xxx新增了一篇博客A。
Subscriber2 收到通知:xxx新增了一篇博客A。
-----目标变化-----
Subscriber1 收到通知:xxx更新了一篇博客A。
Subscriber2 收到通知:xxx更新了一篇博客A。
Subscriber3 收到通知:xxx更新了一篇博客A。
-----目标变化-----
Subscriber1 收到通知:xxx新增了一篇博客B。
Subscriber3 收到通知:xxx新增了一篇博客B。