概述
在现实世界中,许多对象并不是独立存在的,其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变。例如,某种商品的物价上涨时会导致部分商家高兴,而消费者伤心;还有,当我们开车到交叉路口时,遇到红灯会停,遇到绿灯会行。这样的例子还有很多,例如,股票价格与股民、微信公众号与微信用户、气象局的天气预报与听众、小偷与警察等。在软件世界也是这样,例如,Excel 中的数据与折线图、饼状图、柱状图之间的关系;MVC 模式中的模型与视图的关系;事件模型中的事件源与事件处理者。所有这些,如果用观察者模式来实现就非常方便。
(转:http://c.biancheng.net/view/1390.html)
定义
定义对象间一种一对多的依赖关系,每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。
举个栗子
假设微信用户就是观察者,微信公众号是被观察者,有多个微信用户关注了“程序猿”这个公众号,当这个公众号更新时就会通知这些订阅的微信用户。
抽象观察者
里面只定义了一个更新的方法
public interface Observer {
public void update(String messge);
}
具体观察者
微信用户是观察者,里面实现了更新的方法
public class WeixinUser implements Observer {
private String name;
public WeixinUser(String name){
this.name = name;
}
@Override
public void update(String messge) {
System.out.println(name+"-"+messge);
}
}
抽象被观察者
抽象被观察者,提供了attach,detach,notify 三个方法
public interface Subject {
//增加订阅者
public void attach(Observer observer);
//删除订阅者
public void detach(Observer observer);
//通知订阅者更新消息
public void notify(String message);
}
具体被观察者
微信公众号是具体主题(具体被观察者),里面存储了订阅该公众号的微信用户,并实现了抽象主题中的方法;
public class SubscriptionSubject implements Subject {
//存储订阅公众号的微信用户
private List<Observer> weixinUserlist = new ArrayList<Observer>();
@Override
public void attach(Observer observer) {
weixinUserlist.add(observer);
}
@Override
public void detach(Observer observer) {
weixinUserlist.remove(observer);
}
@Override
public void notify(String message) {
for(Observer observer:weixinUserlist){
observer.update(message);
}
}
}
客户端调用
public class Client {
public static void main(String[] args) {
SubscriptionSubject mSubscription = new SubscriptionSubject();
//创建微信用户
WeixinUser user1 = new WeixinUser("用户1");
WeixinUser user2 = new WeixinUser("用户2");
WeixinUser user3 = new WeixinUser("用户3");
//订阅公众号
mSubscription.attach(user1);
mSubscription.attach(user2);
mSubscription.attach(user3);
//公众号更新发出消息给订阅的微信用户
mSubscription.notify("微信要更新内容了!");
}
}
输出结果
用户1-微信要更新内容了!
用户2-微信要更新内容了!
用户3-微信要更新内容了!
观察者模式的使用场景和优缺点
- 使用场景
- 关联行为场景,需要注意的是,关联行为的是可拆分的,而不是“组合”关系
- 事件多级触发场景
- 跨系统的消息交换场景,如消息队列,事件总线的处理机制。
- 优点
- 观察者和被观察者之间是抽象耦合,容易扩展
- 方便建立一套触发机制
- 缺点
- 在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者,多个观察者,开发,调试等内容会比较复杂,而且在java中消息的通知一般是顺序执行的,那么一个观察者卡顿,会影响整体的执行效率,这种情况下,一般会采用异步方式。
借鉴刘望舒《Android进阶之光》