代码拉取完成,页面将自动刷新
观察者模式(Observer Pattern),定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
该模式属于行为模式,观察者模式也叫作发布订阅模式。
观察者模式主要用于,在行为之间建立一套触发机制。如微信朋友圈的通知、MQ等
我们模拟一下鼠标点击触发事件。
我们首先需要一个事件模型,来表示事件源
@Data
@Accessors(chain = true)
public class Event {
//事件源, 事件是由谁发起的保存起来
private Object source;
//事件触发, 要通知谁
private Object target;
//事件触发, 要做什么动作, 回调!
private Method callback;
//事件的名称, 触发的是什么事件
private String trigger;
//事件触发的时间
private long time;
//构造
public Event(Object target, Method callback) {
this.target = target;
this.callback = callback;
}
}
随后我们需要一个事件监听器,来监听和触发回调事件
public class EventLisenter {
//保存事件的容器
protected Map<String, Event> events = new HashMap<String, Event>();
//将事件名称和回调对象添加到事件容器中
//事件名称和一个目标对象来触发事件
public void addLisenter(String eventType, Object target) {
try {
this.addLisenter(
eventType,
target,
target.getClass()
.getMethod("on" + toUpperFirstCase(eventType), Event.class));
} catch (Exception e) {
e.printStackTrace();
}
}
private void addLisenter(String eventType, Object target, Method callback) {
//注册事件
events.put(eventType, new Event(target, callback));
}
//触发, 只要有动作就触发
private void trigger(Event event) {
event.setSource(this);
event.setTime(System.currentTimeMillis());
try {
//发起回调
if (event.getCallback() != null) {
//用反射调用它的回调函数
event.getCallback().invoke(event.getTarget(), event);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//事件名称触发
protected void trigger(String trigger) {
if (!this.events.containsKey(trigger)) {
return;
}
trigger(this.events.get(trigger).setTrigger(trigger));
}
//逻辑处理的私有方法, 首字母大写
private String toUpperFirstCase(String str) {
char[] chars = str.toCharArray();
chars[0] -= 32;//采用阿斯特码方式获取
return String.valueOf(chars);
}
}
接下来我们定义鼠标的行为以及回调定义
public class Mouse extends EventLisenter {
public void click() {
System.out.println("调用单击方法");
this.trigger(MouseEventType.ON_CLICK);
}
public void doubleClick() {
System.out.println("调用双击方法");
this.trigger(MouseEventType.ON_DOUBLE_CLICK);
}
public void up() {
System.out.println("调用弹起方法");
this.trigger(MouseEventType.ON_UP);
}
public void down() {
System.out.println("调用按下方法");
this.trigger(MouseEventType.ON_DOWN);
}
public void move() {
System.out.println("调用移动方法");
this.trigger(MouseEventType.ON_MOVE);
}
public void wheel() {
System.out.println("调用滚动方法");
this.trigger(MouseEventType.ON_WHEEL);
}
public void over() {
System.out.println("调用悬停方法");
this.trigger(MouseEventType.ON_OVER);
}
public void blur() {
System.out.println("调用获焦方法");
this.trigger(MouseEventType.ON_BLUR);
}
public void focus() {
System.out.println("调用失焦方法");
this.trigger(MouseEventType.ON_FOCUS);
}
}
回调定义
public interface MouseEventType {
//单击
String ON_CLICK = "click";
//双击
String ON_DOUBLE_CLICK = "doubleClick";
//弹起
String ON_UP = "up";
//按下
String ON_DOWN = "down";
//移动
String ON_MOVE = "move";
//滚动
String ON_WHEEL = "wheel";
//悬停
String ON_OVER = "over";
//失焦
String ON_BLUR = "blur";
//获焦
String ON_FOCUS = "focus";
}
具体回调
public class MouseEventCallback {
public void onClick(Event e) {
System.out.println("===========触发鼠标单击事件==========" + "\n" + e);
}
public void onDoubleClick(Event e) {
System.out.println("===========触发鼠标双击事件==========" + "\n" + e);
}
public void onUp(Event e) {
System.out.println("===========触发鼠标弹起事件==========" + "\n" + e);
}
public void onDown(Event e) {
System.out.println("===========触发鼠标按下事件==========" + "\n" + e);
}
public void onMove(Event e) {
System.out.println("===========触发鼠标移动事件==========" + "\n" + e);
}
public void onWheel(Event e) {
System.out.println("===========触发鼠标滚动事件==========" + "\n" + e);
}
public void onOver(Event e) {
System.out.println("===========触发鼠标悬停事件==========" + "\n" + e);
}
public void onBlur(Event e) {
System.out.println("===========触发鼠标失焦事件==========" + "\n" + e);
}
public void onFocus(Event e) {
System.out.println("===========触发鼠标获焦事件==========" + "\n" + e);
}
}
测试执行
public class MouseEventTest {
public static void main(String[] args) {
try {
//定义事件
MouseEventCallback callback = new MouseEventCallback();
//注册事件
Mouse mouse = new Mouse();
mouse.addLisenter(MouseEventType.ON_CLICK, callback);
mouse.addLisenter(MouseEventType.ON_MOVE, callback);
mouse.addLisenter(MouseEventType.ON_WHEEL, callback);
mouse.addLisenter(MouseEventType.ON_OVER, callback);
//调用点击方法,触发事件
mouse.click();
//失焦事件,触发事件
mouse.blur();
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出
调用单击方法
===========触发鼠标单击事件==========Event(xxxxxxxxxxxxxx)
调用获焦方法
我们可以看到 click
方法的时间被触发,而 blur
的时间未被触发,这是因为我们没有在监听器中注册 blur
对应的事件。
首先引入maven
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
定义观察者/订阅
public class GuavaEvent {
@Subscribe//订阅注解
public void subscribe(String str) {
//业务逻辑
System.out.println("执行 String 方法,传入的参数是:" + str);
}
@Subscribe//订阅注解
public void subscribe(Integer a) {
//业务逻辑
System.out.println("执行 Integer 方法,传入的参数是:" + a);
}
}
测试
public static void main(String[] args) {
//事件总线
EventBus eventbus = new EventBus();
//事件定义与注册
GuavaEvent guavaEvent = new GuavaEvent();
eventbus.register(guavaEvent);
//发布事件
eventbus.post(1);
eventbus.post("tom");
}
输出
执行 Integer 方法,传入的参数是:1
执行 String 方法,传入的参数是:tom
我们可以看到 EventBus
可以自动匹配参数类型。
还有一点需要说明,被 @Subscribe
修饰的方法有且只能有一个参数
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。