设计模式-观察者模式
定义
观察者模式(Observer Pattern)又叫发布-订阅模式。定义一种一对多的依赖关系。
一个主题对象可以被多个观察者对象同事监听,使得每当主题对象状态发生变化时,所有依赖于它的对象都会得到通知并被自动更新
属于行为模式。
适用场景
- 当一个抽象模型包含2个方面内容,其中一个方面依赖于另一个方面;
- 其他一个或多个对象的变化依赖于另一个对象的变化;
- 实现类似广播机制的功能,无需知道具体收听者,只需分化
- 多层级嵌套,形成一种链式触发机制,使得事件具备跨域通知
代码示例
手写观察者模式
拿鼠标举例
- 创建事件类
package com.black.design.pattern.observer.mouse;
import java.lang.reflect.Method;
// 事件类
public class Event {
// 事件名称
private String name;
// 事件源
private Object source;
// 事件触发,通知目标(观察者)
private Object target;
// 观察者回调函数
private Method callback;
// 创建事件的时间
private String createTime;
public Event(String name) {
this.name = name;
}
public Event(Object target, Method callback) {
this.target = target;
this.callback = callback;
}
public String getName() {
return name;
}
public Object getSource() {
return source;
}
public Object getTarget() {
return target;
}
public Method getCallback() {
return callback;
}
public String getCreateTime() {
return createTime;
}
public Event setName(String name) {
this.name = name;
return this;
}
public Event setSource(Object source) {
this.source = source;
return this;
}
public Event setTarget(Object target) {
this.target = target;
return this;
}
public Event setCallback(Method callback) {
this.callback = callback;
return this;
}
public Event setCreateTime(String createTime) {
this.createTime = createTime;
return this;
}
}
- 创建事件监听类,当事件触发时,默认调用 回调类对应的on方法
package com.black.design.pattern.observer.mouse;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
// 被观察者的抽象
public class EventListener {
// 事件
protected Map<String, Event> events = new HashMap<String, Event>();
// 感兴趣的事件
public void interestEvent(String eventType, Object target, Method callback) {
events.put(eventType, new Event(target, callback));
}
// 感兴趣的事件
public void interestEvent(String eventType, Object target) throws NoSuchMethodException, SecurityException {
// 回调方法
Method callback = target.getClass().getMethod("on" + toUpperFirstChar(eventType), Event.class);
interestEvent(eventType, target, callback);
}
// 首字母转为大写
private String toUpperFirstChar(String eventType) {
char [] chars = eventType.toCharArray();
chars[0] -=32;
return new String(chars);
}
// 触发事件
protected void triger(String triger) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (!events.containsKey(triger)) {return;}
Event t = events.get(triger);
t.setSource(this);
t.setCreateTime(String.valueOf(System.nanoTime()));
if(t.getCallback() != null) {
t.getCallback().invoke(t.getTarget(), t);
}
}
}
- 创建鼠标事件类型
package com.black.design.pattern.observer.mouse;
// 事件类型
public class MouseEventType {
// 单击事件
public static final String ON_CLICK="click";
// 双击事件
public static final String ON_DOUBLE_CLICK="doubleClick";
// 移动事件
public static final String ON_MOVE="move";
// 滑动事件
public static final String ON_SCROLL="scroll";
}
- 创建鼠标类
package com.black.design.pattern.observer.mouse;
import java.lang.reflect.InvocationTargetException;
// 鼠标
public class Mouse{
// 鼠标监听器
private MouseEventListener listener;
// 注册监听器
public void registerListener(MouseEventListener listener) {
this.listener = listener;
}
// 单击
public void click() {
System.out.println("单击鼠标");
triger(MouseEventType.ON_CLICK);
}
// 双击
public void doubleClick() {
System.out.println("双击鼠标");
triger(MouseEventType.ON_DOUBLE_CLICK);
}
// 移动
public void move() {
System.out.println("鼠标移动");
triger(MouseEventType.ON_MOVE);
}
// scroll
public void scroll() {
System.out.println("鼠标滑动");
triger(MouseEventType.ON_SCROLL);
}
// 触发监听器
private void triger(String eventType) {
if(listener != null) {
try {
listener.triger(eventType);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
}
}
- 创建回调类
package com.black.design.pattern.observer.mouse;
// 回调类
public class MouseCallBack {
// 点击回调
public void onClick(Event t) {
System.out.println("回调 on click");
}
// 双击回调
public void onDoubleClick(Event t) {
System.out.println("回调 on double click");
}
}
- 测试
package com.black.design.pattern.observer.mouse;
import java.awt.event.MouseListener;
// 测试类
public class MouseTest {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
// 实例化鼠标
Mouse mouse = new Mouse();
// 回调类
MouseCallBack callBack = new MouseCallBack();
// 实例化鼠标事件监听器
MouseEventListener listener = new MouseEventListener();
// 感兴趣的事件是 单击,如果鼠标单击则会回调 callBack 类
listener.interestEvent(MouseEventType.ON_CLICK, callBack);
// 鼠标注册监听器,监听器监听鼠标的行为
mouse.registerListener(listener);
// 单击鼠标
System.out.println("======单击鼠标======");
mouse.click();
// 双击鼠标
System.out.println("======双击鼠标======");
mouse.doubleClick();
}
}
运行结果:
======单击鼠标======
单击鼠标
监听到来自com.black.design.pattern.observer.mouse.MouseEventListener的click事件
事件回调onClick方法
======双击鼠标======
双击鼠标
JDK 提供的观察者模式
- 创建一个 Observer 接口的实现类
package com.black.design.pattern.observer.jdk;
import java.util.Observable;
import java.util.Observer;
/**
* 观察者
* @author black
*
*/
public class MyObserver implements Observer{
private String name;
public MyObserver(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
Target target = (Target)o;
System.out.println(name + " 接收到信息: " + arg);
}
}
- 创建 Observable 类的子类
package com.black.design.pattern.observer.jdk;
import java.util.Observable;
import java.util.Observer;
/**
* 被观察者
* @author black
*
*/
public class Target extends Observable {
@Override
public synchronized void addObserver(Observer o) {
super.addObserver(o);
}
public void postNotice(String notice) {
System.out.println("发布消息: " + notice);
setChanged();
notifyObservers(notice);
}
}
- 测试类
package com.black.design.pattern.observer.jdk;
/**
* 观察者测试类
* @author black
*
*/
public class ObserverTest {
public static void main(String[] args) {
// 创建被观察者 target
Target target = new Target();
// 创建2个观察者 blackMyObserver 和 xiaomingMyObserver
MyObserver blackMyObserver = new MyObserver("black");
MyObserver xiaomingMyObserver = new MyObserver("xiaoming");
target.addObserver(blackMyObserver);
target.addObserver(xiaomingMyObserver);
// 被观察者 target 发出一个通知
System.out.println("=======第1条通知=========");
target.postNotice("明天下午8点停电!");
System.out.println("=======第2条通知=========");
target.postNotice("后天早上8点点打卡!");
}
}
测试结果:
=======第1条通知=========
发布消息: 明天下午8点停电!
xiaoming 接收到信息: 明天下午8点停电!
black 接收到信息: 明天下午8点停电!
=======第2条通知=========
发布消息: 后天早上8点点打卡!
xiaoming 接收到信息: 后天早上8点点打卡!
black 接收到信息: 后天早上8点点打卡!
Guava 提供的观察者模式
- 引入 guava jar 包
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
- 创建 事件类
package com.black.design.pattern.observer.guava;
import com.google.common.eventbus.Subscribe;
/**
* 使用@Subscribe注解,订阅观察的方法
* @author black
*
*/
public class GuavaEvent {
@Subscribe
public void subscribe(String str) {
//执行业务逻辑
System.out.println("调用 subscribe,传入参数:" + str);
}
}
- 创建测试类
package com.black.design.pattern.observer.guava;
import com.google.common.eventbus.EventBus;
public class GuavaEventTest {
public static void main(String[] args) {
// 创建事件总线
EventBus eventBus = new EventBus();
// 创建自定义的事件
GuavaEvent guavaEvent = new GuavaEvent();
// 将自定义的事件注册到 EventBus 中
eventBus.register(guavaEvent);
// EventBus 发送消息,各个事件会接受到这个消息
eventBus.post("black");
}
}
测试结果:
调用 subscribe,传入参数:black
本文来自博客园,作者:不安分的黑娃,转载请注明原文链接:https://www.cnblogs.com/lihw-study/p/15227053.html