1、定义
观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
2、UML类图
-
抽象目标角色(Subject):目标角色知道它的观察者,可以有任意多个观察者观察同一个目标。并且提供注册和删除观察者对象的接口。目标角色往往由抽象类或者接口来实现。
-
抽象观察者角色(Observer):为那些在目标发生改变时需要获得通知的对象定义一个更新接口。抽象观察者角色主要由抽象类或者接口来实现。
-
具体目标角色(Concrete Subject):将有关状态存入各个Concrete Observer 对象。当它的状态发生改变时, 向它的各个观察者发出通知。
-
具体观察者角色(Concrete Observer):存储有关状态,这些状态应与目标的状态保持一致。实现Observer 的更新接口以使自身状态与目标的状态保持一致。在本角色内也可以维护一个指向Concrete Subject 对象的引用。
3、实例
a、背景
微信用户就是观察者,微信公众号是被观察者,有多个的微信用户关注了tong'yi'ge公众号,当这个公众号更新时就会通知这些订阅的微信用户。
b、实例
抽象观察者Observer
public interface Observer {
public void update(String message);
}
具体观察者ConcrereObserver
public class WeiXinUser implements Observer{
//微信用户名
private String name;
public WeiXinUser(String name) {
this.name = name;
}
@Override
public void update(String message) {
// TODO Auto-generated method stub
System.out.println(name+"-"+message);
}
}
抽象被观察者Subject
抽象主题,提供attach、detach、notify三个方法
public interface Subject {
//增加订阅者
public void attach(Observer observer);
//删除订阅者
public void detach(Observer observer);
//通知订阅者更新消息
public void notify(Observer observer);
}
具体被观察者ConcreteSubject
微信公众号是具体主题(具体被观察者),里面存储了订阅该公众号的微信用户,并实现了抽象主题中的方法:
public class SubscriptionSubject implements Subject{
//存储订阅公众号的微信用户
private List<Observer> weixinUserlist = new ArrayList<Observer>();
@Override
public void attach(Observer observer) {
// TODO Auto-generated method stub
weixinUserlist.add(observer);
}
@Override
public void detach(Observer observer) {
// TODO Auto-generated method stub
weixinUserlist.remove(observer);
}
@Override
public void notify(String message) {
// TODO Auto-generated method stub
for(Observer observer : weixinUserlist) {
observer.update(message);
}
}
}
客户端调用Client
public class Client {
public static void main(String[] args) {
SubscriptionSubject msubscriptionSubject = new SubscriptionSubject();
//创建微信用户
WeiXinUser user1 = new WeiXinUser("林晓雯");
WeiXinUser user2 = new WeiXinUser("张亚楠");
WeiXinUser user3 = new WeiXinUser("王静怡");
WeiXinUser user4 = new WeiXinUser("刘晓飞");
WeiXinUser user5 = new WeiXinUser("董思敏");
//订阅公众号
msubscriptionSubject.attach(user1);
msubscriptionSubject.attach(user2);
msubscriptionSubject.attach(user3);
msubscriptionSubject.attach(user4);
msubscriptionSubject.attach(user5);
//公众号更新发出消息给订阅的用户
msubscriptionSubject.notify("微信公众号更新了");
}
}
4、优点
-
观察者和被观察者是抽象耦合的。
-
建立一套触发机制。
5、缺点
-
如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
-
如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
-
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
6、使用场景
-
一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
-
一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
-
一个对象必须通知其他对象,而并不知道这些对象是谁。
-
需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。