观察者模式(Observer):
又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
应用:
1. 何时使用
- 一个对象状态改变,所有的依赖对象都将得到通知
2. 方法
- 使用面向对象技术
3. 优点
- 观察者和被观察者是抽象耦合的
- 建立了一套触发机制
4. 缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
- 如果观察者和观察目标间有循环依赖,可能导致系统崩溃
- 没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的
5. 使用场景
- 关联行为场景
- 事件多级触发场景
- 跨系统的消息变换场景,如消息队列的处理机制
6. 应用实例
- 手机丢了,委托别人给其他人发消息通知
- 通知:领导来了,员工做出的反应
7. 注意事项
- 避免循环引用
- 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式
实现:
通知数据库要更新了,收到通知的做了更新,未收到的没有做更新
1.通知者接口
package com...; import java.util.Observer; /** * 通知者接口 */ public interface Subjects { //增加 public void add(ObServer observer); //删除 public void remove(ObServer observer); //通知 public void notifyObservers(); //状态 public void setAction(String action); public String getAction(); }
2.观察者
package com...; /** * 观察者 */ public abstract class ObServer { protected String name; protected Subjects subject; public ObServer(String name, Subjects subject) { this.name = name; this.subject = subject; } public abstract void update(); }
3.具体通知者
package com...; import java.util.LinkedList; import java.util.List; /* *具体通知者 */ public class Secretary1 implements Subjects { //接收通知DB列表 private List<ObServer> obServers = new LinkedList<>(); private String action; @Override public void add(ObServer observer) { obServers.add(observer); } @Override public void remove(ObServer observer) { obServers.remove(observer); } //通知 @Override public void notifyObservers() { for (ObServer observerss: obServers){ observerss.update(); } } @Override public void setAction(String action) { this.action = action; } @Override public String getAction() { return action; } }
4.具体观察者 db1 和 bd2 两个类 继承观察者类
package com...; /* *具体观察者 db1 */ public class DbService1 extends ObServer { public DbService1(String name, Subjects subject) { super(name, subject); } @Override public void update() { System.out.println(subject.getAction() + name + "做了更新...."); } } package com...; /* *具体观察者 db2 */ public class DbService2 extends ObServer { public DbService2(String name, Subjects subject) { super(name, subject); } @Override public void update() { System.out.println(subject.getAction() + name + "做了更新...."); } }
5.通知者 (Client)
package com...; public class Client { public static void main(String[] args) { //通知者 Secretary1 secretary = new Secretary1(); DbService1 db1= new DbService1("db1", secretary); DbService2 db2 = new DbService2("db2", secretary); //加入通知列表 secretary.add(db1); secretary.add(db2); //db2 未被通知 ->db2移除列表 secretary.remove(db2); secretary.setAction("更新数据库! "); //发通知 secretary.notifyObservers(); } }