0x1、定义
又称
订阅-发布模式
,在对象间定义一个一对多的依赖,当一个对象状态改变时,所有依赖对象都会自动收到通知。被依赖对象称作被观察者
,依赖对象称作观察者
。
听着有点抽象,写个简单例子帮助理解 (蜜蜂、蝴蝶授粉):
// 观察者:昆虫接口 public interface Insect { void startWork(); void stopWork(); } // 具体观察者:蜜蜂 public class Bee implements Insect { private String name; public Bee(String name) { this.name = name; } @Override public void startWork() { System.out.println("蜜蜂【" + name + "】开始传粉"); } @Override public void stopWork() { System.out.println("蜜蜂【" + name + "】停止传粉"); } } // 具体观察者:蜜蜂 public class Butterfly implements Insect { private String name; public Butterfly(String name) { this.name = name; } @Override public void startWork() { System.out.println("蝴蝶【" + name + "】开始传粉"); } @Override public void stopWork() { System.out.println("蝴蝶【" + name + "】停止传粉"); } } // 被观察者:植物接口 public interface Plant { void registerInsect(Insect insect); void unregisterInsect(Insect insect); void notifyInsect(boolean isOpen); } // 具体被观察者:花类 public class Flower implements Plant { private final List<Insect> insects = new ArrayList<>(); @Override public void registerInsect(Insect insect) { insects.add(insect); } @Override public void unregisterInsect(Insect insect) { insects.remove(insect); } @Override public void notifyInsect(boolean isOpen) { if(isOpen) { System.out.println("花开咯~"); for(Insect insect: insects) insect.startWork(); } else { System.out.println("花谢了~"); for(Insect insect: insects) insect.stopWork(); } } // 定义了一个批量解绑的方法 public void unregisterAllInsect() { for(int i = 0; i < insects.size(); i++) unregisterInsect(insects.get(i)); } } // 测试用例 public class ObserverTest { public static void main(String[] args) { Flower flower = new Flower(); // 创建并注册观察者 for (int i = 1; i < 4; i++) { flower.registerInsect(new Bee(i + "")); flower.registerInsect(new Butterfly(i + "")); } // 通知观察者 flower.notifyInsect(true); System.out.println("=== 开花期已过 ==="); // 通知观察者 flower.notifyInsect(false); // 解绑所有观察者 flower.unregisterAllInsect(); } }
代码运行输出结果如下:
网络异常,图片无法展示
|
代码非常简单,老规矩带出UML类图、角色解读、适用场景和优缺点:
网络异常,图片无法展示
|
角色解读:
- Subject (被观察者) → 又称发布者、主题、目标、被订阅者等,通常指观察者关心的相关对象集合;
- ConcreteSubject (具体被观察者) → 实现了被观察者定义方法的具体实现类,类中有存放观察者的容器;
- Observer (观察者) → 又称订阅者,提供被观察者变化对应的反应方法;
- ConcreteObserver (具体被观察者) → 观察者的具体实现;
适用场景:
- 对象状态改变需要修改其他对象时;
- 对象发生改变时只想发送通知,而不需要知道接收者是谁;
- 链式触发机制:在系统中构建一个触发链,A影响B、B影响C;
- 创建基于事件触发的场景;
优点
观察者与目标间的抽象解耦,提高扩展性,动态联动(一个操作引起其他相关操作)
缺点
互为观察者和被观察者间有相互依赖时要避免相互通知引起的死循环!增加代码的理解难度,观察者对象多时,被观察者通知观察者花费的时间会变成,某正程度上影响程序的效率。