观察者模式
定义: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
如何解决:使用面向对象技术,可以将这种依赖关系弱化。
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
举例(有一个微信公众号服务,不定时发布一些消息,关注公众号就可以收到推送消息,取消关注就收不到推送消息。)
定义一个抽象被观察者接口
public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObserver(); }
定义一个抽象观察者接口
public interface Observer { public void update(String message); }
定义被观察者,实现了Observerable接口,对Observerable接口的三个方法进行了具体实现,同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可。
public class WechatServer implements Subject { private List<Observer> list; private String message; public WechatServer() { list = new ArrayList<Observer>(); } @Override public void registerObserver(Observer o) { // TODO Auto-generated method stub list.add(o); } @Override public void removeObserver(Observer o) { // TODO Auto-generated method stub if (!list.isEmpty()) { list.remove(o); } } @Override public void notifyObserver() { // TODO Auto-generated method stub for (Observer o : list) { o.update(message); } } public void setInfomation(String s) { this.message = s; System.out.println("微信服务更新消息: " + s); // 消息更新,通知所有观察者 notifyObserver(); } }
定义具体观察者,微信公众号的具体观察者为用户User
public class User implements Observer { private String name; private String message; public User(String name) { this.name = name; } @Override public void update(String message) { this.message = message; read(); } public void read() { System.out.println(name + " 收到推送消息: " + message); } }
编写一个测试类
public class MainTest { public static void main(String[] args) { WechatServer server = new WechatServer(); Observer userZhang = new User("ZhangSan"); Observer userLi = new User("LiSi"); Observer userWang = new User("WangWu"); server.registerObserver(userZhang); server.registerObserver(userLi); server.registerObserver(userWang); server.setInfomation("PHP是世界上最好用的语言!"); System.out.println("----------------------------------------------"); server.removeObserver(userZhang); server.setInfomation("JAVA是世界上最好用的语言!"); } }