观察者模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
使用场景
一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
代码
事件类,定义了事件源头、被回调对象、回调方法,等其他可用的信息
/**
* 事件
*/
public class Event {
//事件源
private Object source;
//被回调对象
private Object target;
//回调方法
private Method callback;
//触发的类型
private Enum trigger;
//时间
private long time;
public Event(Object target, Method callback) {
this.target = target;
this.callback = callback;
}
// 省略get/set方法
监听器,事件源对象继承监听器,可以使用触发trigger方法,通过反射调用到目标对象的方法。
/**
* 事件监听
*/
public class EventListener {
// 注册
protected Map<Enum,Event> events = new HashMap<>();
public void addListener(Enum eventType, Object target, Method callback){
// 传参数目标target是为了反射获取方法
Event event = new Event(target,callback);
events.put(eventType,event);
}
//触发函数
public void trigger(Enum eventType) {
if(!this.events.containsKey(eventType)){return;}
// 设置源和触发类型
Event event = this.events.get(eventType);
event.setTime(System.currentTimeMillis());
event.setSource(this)
.setTrigger(eventType);
Object observer = event.getTarget();
Method callback = event.getCallback();
try {
callback.invoke(observer,event);
} catch (Exception e) {
e.printStackTrace();
}
}
}
枚举类型
/**
* 事件枚举
*/
public enum EventType {
SUBJECT_ADD,SUBJECT_REMOVE;
}
观察者,即目标对象
/**
* 观察者,即需要回调通知的对象
*/
public class Observer {
//通知,如果目标执行了方法,则执行此方法,打印event信息
public void advice(Event event){
System.out.println("观察者执行了advice()方法,event:"+event);
}
}
目标,即事件源头
/**
* 目标
*/
public class Subject extends EventListener{
public void add(){
System.out.println("目标执行了add()");
// trigger(EventType.SUBJECT_ADD), 这里可以使用代理模式,更优雅
trigger(EventType.SUBJECT_ADD);
}
public void remove(){
System.out.println("目标执行了remove()");
trigger(EventType.SUBJECT_REMOVE);
}
}
测试类
/**
* 测试
*/
public class TestObserver {
public static void main(String[] args) throws NoSuchMethodException {
// 源
Subject subject = new Subject();
// 观察者
Observer observer = new Observer();
// 回调方法
Method advice = observer.getClass().getMethod("advice", new Class[]{Event.class});
// 注册一个监听添加事件
subject.addListener(EventType.SUBJECT_ADD,observer,advice);
// 调用目标的添加方法
subject.add();
}
}
结果
目标执行了add(),观察者也接受到了通知。