博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
观察者模式
阅读量:6083 次
发布时间:2019-06-20

本文共 3290 字,大约阅读时间需要 10 分钟。

定义

定义对象的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式是行为型模式之一。包含观察者模式包括观察者与被观察者两个基本元素,观察者会注册到被观察者中,而被观察者会保持和观察者的对应关系。

如果被观察的对象产生一些观察者感兴趣的变更,则观察者会得到通知从而去执行相关的操作。

常见的观察者模式

提到观察者模式,首先会想到前端中常用的事件机制。例如为dom元素绑定事件:

$(document).click(function (e) {    console.dir(e);});

这里的匿名function就是观察者,而document则是被观察者,.click(function)则是观察者注册的过程,此后document发生click事件时,被观察者则会收到通知,从而执行自己的逻辑console.dir(e)。

使用观察者模式

现在我们使用Java来模拟观察者模式。

先创建事件,包含事件源,通知目标,回调方法以及触发者等属性。

/** * 事件 */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;    }    // 省略getter、setter}

定义事件类型,此处定义添加、删除两种类型。

/** * 事件类型 */public enum EventType {    /**     * 添加     */    ADD,    /**     * 删除     */    RMOVE}

定义抽象被观察者(主题),包含主题名称,保持与观察者引用映射的容器,以及事件触发的方法。

import java.lang.reflect.Method;import java.util.HashMap;import java.util.Map;/** * 抽象主题 * 定义主题通用的容器、事件注册及事件触发 */public class AbstractSubject {    protected String name;    protected Map
eventMap = new HashMap<>(); // 注册容器 public AbstractSubject() {} protected AbstractSubject(String name) { this.name = name; } /** * 事件注册 * @param eventType * @param target * @param callback */ public void addLisenter(Enum eventType, Object target, Method callback) { eventMap.put(eventType, new Event(target, callback)); } /** * 事件触发 * @param eventType */ protected void trigger(Enum eventType) { Event event = this.eventMap.get(eventType); if(null == event) { return; } event.setSource(this); event.setTrigger(eventType.toString()); event.setTime(System.currentTimeMillis()); try { event.getCallback().invoke(event.getTarget(), event); } catch (Exception e1) { e1.printStackTrace(); } } // 省略getter、setter}

定义具体主题:

/** * 主题,被观察者 */public class Subject extends AbstractSubject {    public Subject(String name) {        super.name = name;    }    public void add() {        trigger(EventType.ADD);    }    public void remove() {        trigger(EventType.RMOVE);    }}

定义观察者,包含添加、删除事件对应的回调方法。

/** * 观察者 */public class Observer {    public void onAdd(Event event) {        System.out.println("收到" + event.getTrigger() + "的添加事件");    }    public void onRemove(Event event) {        System.out.println("收到" + event.getTrigger() + "的删除事件");    }}

测试类:

/** * 测试类 */public class Test {    public static void main(String[] args) throws NoSuchMethodException {        // 观察者        Observer observer = new Observer();        // 观察者收到通知后执行的方法        Method onAdd = Observer.class.getMethod("onAdd", Event.class);        Method onRemove = Observer.class.getMethod("onRemove", Event.class);        // 被观察者        Subject subject = new Subject("目标1号");        // 事件绑定        subject.addLisenter(EventType.ADD, observer, onAdd);        subject.addLisenter(EventType.RMOVE, observer, onRemove);        // 被观察者触发事件        subject.add();        subject.remove();    }}

其中,得到观察者和主题对象后,进行观察者的注册,然后主题执行动作触发事件,这是整个流程。

如果需要做成主题和观察者一对多的映射,则将Event的target改成集合类型,如下:

private List targets; // 通知目标

转载地址:http://jgkwa.baihongyu.com/

你可能感兴趣的文章
我的友情链接
查看>>
解决zabbix_get 获取不到自定义key一例
查看>>
DBNULL和NULL
查看>>
Confluence 6 有关 AD 的一些特殊说明
查看>>
linux系统管理之五:开机、关机、服务状态及系统密码修改
查看>>
Windows环境下的NodeJS+NPM+Bower安装配置
查看>>
LeetCode:Valid Number - 判断字符串中内容是否为数字
查看>>
Android 4.0 硬件加速
查看>>
Windows XP与NTP服务器自动更新时间的调整
查看>>
我的友情链接
查看>>
ubuntu 主机ssh root solaris虚拟机时候,输入密码报错 public key解决
查看>>
Silverlight和服务器端通信
查看>>
cookie注入&中转注入笔记
查看>>
跟Howard学LESS之初见LESS
查看>>
wap网页图片适配解决方案
查看>>
小菜学Chromium开发(一)OpenGL学习
查看>>
注解入门
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
【MySQL】online ddl 工具之pt-online-schema-change
查看>>