观察者模式
定义
Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
解释
观察者模式主要有两个角色,一个被观察者,多个观察者,这个被观察者是与多个观察者关联在一起的。
当这个被观察者执行任务后,数据会被更新,所有观察者会被唤醒,自动更新被监控观察者的信息。
代码实现
准备
现在我们输入一个十进制数字,它会被存入被观察者实体中,而这时会将转换为二进制,八进制,十六进制的观察者唤醒。这样输入一个数字,就回打印出这个数字对应的二进制,八进制,十六进制。
被观察者
Subject类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package org.example.observer;import java.util.ArrayList;import java.util.List;public class Subject { private List<Observer> observers = new ArrayList<>(); private int state ; public int getState () { return state ; } public void setState (int state) { System.out.println("输入数字:" + state); this .state = state ; notifyAllObservers(); } public void attach (Observer observer) { observers.add(observer); } public void notifyAllObservers () { for (Observer observer : observers){ observer.update(); } } }
观察者
观察者抽象类
1 2 3 4 5 6 7 8 9 package org.example.observer;public abstract class Observer { protected Subject subject ; public abstract void update () ; }
转换为二进制的观察者
1 2 3 4 5 6 7 8 9 10 11 12 13 package org.example.observer;public class BinaryObserver extends Observer { public BinaryObserver (Subject subject) { this .subject = subject ; this .subject.attach(this ); } @Override public void update () { System.out.println("输入数字的二进制:" +Integer.toBinaryString(this .subject.getState())); } }
转换为八进制的观察者
1 2 3 4 5 6 7 8 9 10 11 12 13 package org.example.observer;public class OctalObserver extends Observer { public OctalObserver (Subject subject) { this .subject = subject ; this .subject.attach(this ); } @Override public void update () { System.out.println("输入数字的八进制:" +Integer.toOctalString(this .subject.getState())); } }
转换为十六进制的观察者
1 2 3 4 5 6 7 8 9 10 11 12 13 package org.example.observer;public class HexObserver extends Observer { public HexObserver (Subject subject) { this .subject = subject ; this .subject.attach(this ); } @Override public void update () { System.out.println("输入数字的十六进制:" +Integer.toHexString(this .subject.getState())); } }
场景实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class App { public static void main (String[] args) { Subject subject = new Subject(); new HexObserver(subject); new OctalObserver(subject); new BinaryObserver(subject); subject.setState(10 ); System.out.println(); subject.setState(20 ); } }
观察者模式扩展
被观察者可以被抽象出来,使得其具有良好的扩展性。
应用场景
关联行为场景,每个行为之间是关联的。一个行为的触发会影响其他行为。
事件的多级触发。
跨系统的消息交换。比如远程调用就需要观察者模式。
观察者模式优缺点
优点
观察者和被观察者之间是抽象耦合的,这使得观察者和被观察者都很容易的扩展。
观察者模式建立了一套触发机制,观察者模式每个观察者与被观察者都遵循单一职责,当被观察者被执行,就回触发观察者,这就形成一个触发链。
缺点
观察者模式需要考虑开发效率和运行效率。java中消息通知是顺序执行,一个观察者失败会影响整体效率,一般采用异步。
注意事项
广播链问题。观察者模型形成的触发链不能太长,如果太长,触发链中的一个产生错误,整个触发链就毁了。因此在一个观察者模式中最多出现一个对象既是观察者又是被观察者,也就是消息最多转发一次(传递两次)。
异步处理需要考虑线程安全和队列问题。