一,观察者模式
观察者模式又名发布-订阅模式,定义了对象之间的一对多依赖,多个对象同时监听一个对象,当被监听对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新,被监听对象称为主题suject,监听对象称为观察者observer。项目中应用的MQ就是观察者模式的一种表现形式。
二,UML类图
* Subject : 主题类,提供注册,移除,通知观察者类的方法。
* ConcreteSubject : 具体主题类,对观察者进行管理并变更通知。
* Observer : 观察者的顶层类,提供update()方法接收被观察者类的通知。
* ConcreteObserver : 具体观察者类,用来接收被观察者类返回的状态进行业务处理。
三,JDK内置的观察者模式
1,观察者类,实现Observer接口并重写update()方法;
public class JDKObserver implements Observer{
private Observable observable;
public JDKObserver(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
System.out.println("===观察者接收通知===");
}
}
2,被观察者类,继承Observable类
public class JDKObserable extends Observable {
public void changed() {
System.out.println("===发布者发布消息====");
adviced();
}
public void adviced() {
setChanged();
notifyObservers();
}
}
3,执行流程 --- JDK源码分析
* 被观察者类状态变更完成后,首先必须调用父类的setChanged()方法,改变是否通知状态
protected synchronized void setChanged() {
changed = true;
}
* changed状态改为true后,调用notifyObservers()方法,通知观察者类
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
* 可以看到,被观察者类在通知观察者类之前,会将changed状态重新改为false
protected synchronized void clearChanged() {
changed = false;
}
4,测试类
public class JDKObserverTest {
public static void main(String[] args) {
JDKObserable obserable = new JDKObserable();
JDKObserver observer = new JDKObserver(obserable);
obserable.changed();
}
}
* 首先创建一个被观察者类
* 其次依次创建观察者类并传递被观察者类引用,依次绑定为该被观察者类的观察者类
* 执行被观察者的更新方法后,观察者类同步变更
四,自定义观察者模式 --- 通过动态代理实现观察者模式
1,事件VO
public class Event {
// 事件源
private Object source;
// 通知目标
private Object target;
// 回调
private Method method;
public Event(Object source, Object target, Method method) {
this.source = source;
this.target = target;
this.method = method;
}
public Object getSource() {
return source;
}
public void setSource(Object source) {
this.source = source;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
@Override
public String toString() {
return "Event{" + "\r\n" +
"source=" + source + "\r\n" +
", target=" + target + "\r\n" +
", method=" + method + '}';
}
}
2,事件枚举
public enum EventEnum {
ON_ADD,
ON_REMOVE,
ON_EDIT,
ON_QUERY;
}
3,事件绑定
public class EventListener {
protected Map<Enum, Event> eventMap = new HashMap<Enum, Event>();
public void addListener(Enum eventType, Object target, Method callBack) {
// 注册事件
eventMap.put(eventType, new Event(this, target, callBack));
}
protected void trigger(Enum eventType) {
try {
Event event = eventMap.get(eventType);
if (null == event) {
return;
}
event.getMethod().invoke(event.getTarget(), event);
} catch (Exception e) {
e.printStackTrace();
}
}
}
* Map的value可以用List进行替换,实现事件下的多观察者;
4,被观察者类顶层接口
public interface SubjectInterface {
public void add();
public void remove();
}
* 通过动态代理实现,确保强一致性;
5,被观察者类
public class Subject extends EventListener implements SubjectInterface{
public void add() {
System.out.println("调用添加的方法");
trigger(EventEnum.ON_ADD);
}
public void remove() {
System.out.println("调用移除的方法");
trigger(EventEnum.ON_REMOVE);
}
}
6,被观察者类代理对象及方法执行
public class JDKProxy {
public static Object newInstance(final SubjectInterface observer) {
SubjectInterface subjectInterface = (SubjectInterface) Proxy.newProxyInstance(observer.getClass().getClassLoader(),
observer.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(observer, args);
return null;
}
});
return subjectInterface ;
}
}
7,观察者类
public class Observer {
public void advice(Event event) {
System.out.println("========触发事件========" + "\r\n" + event);
}
}
8,客户端
public class ObserverTest {
public static void main(String[] args) {
try {
// 观察者
Observer observer = new Observer();
// 发布者
Subject subject = new Subject();
subject.addListener(EventEnum.ON_ADD, observer, observer.getClass().getMethod("advice", new Class[]{Event.class}));
SubjectInterface proxy = (SubjectInterface) JDKProxy.newInstance(subject);
System.out.println(proxy.getClass());
proxy.add();
} catch (Exception e) {
e.printStackTrace();
}
}
}
* 该实现方式仿照JS的事件绑定Xxx("click", function(){});进行处理。