观察者模式与事件驱动模型
观察者模式:
发布 - 订阅 , 变化 - 更新
事件驱动模型
请求 - 响应, 事件发生 - 事件 处理
2.事件驱动模型
事件源
- 持有监听器列表,或者各种类型监听器
- 可以只需要持有监听器的引用,在具体调用时,通过set将监听器实例set进去.
- 这样做的目的时,不需要让事件源去提供注册和注销的api,直接通过set即可。
//例子,以button为事件源 public class Button { private ClickListener clickListener; private DbClickListener dbClickListener; // setter getter 省略 } //具体使用时 public class ButtonJsp { //持有事件源 private Button button; public ButtonJsp() { button = new Button(); button.setClickListener(new ClickListener(){ public void click(ClickEvent event) { System.out.println("do something") } }); } }
- 提供注册与注销api 给监听器注册(非必须,变种)
- 触发事件,fireEvent
事件对象(AppEvent)
- 可以定义各类事件
- 必须持有事件源
- 可以附带附加信息
监听器
- 持有某个事件,监听事件
- 定义行为,事件触发后会回调此行为
- 向事件源注册和注销自己
Manager类
-
保存事件源列表,在事件源的构造器中注册自己
- 如果有多的事件源对象,此管理器可以很好的做到管理
- 例如事件源是作者,而这里可以维护多个作者
- 或者例如下文中
dapeng
框架里的多个Application
public class Writer { private String name; private String novel; public Writer(String name) { this.name =this.name; Manager.getInstance().add(this); } }
-
维护事件源的信息,拿到具体的事件源后,给监听器注册自己。
- 例子,监听器读者监听作者
Writer
public void register(String writerName) { Manager.getInstance().getWriter(writeName).register(this); }
- 例子,监听器读者监听作者
3.以dapeng-container
为例
- 3.1 监听器
AppListener
public interface AppListener extends EventListener {
public void appRegistered(AppEvent event);
public void appUnRegistered(AppEvent event);
}
持有AppEvent事件,定义注册和注销自己
- 3.2 事件
AppEvent
public class AppEvent extends EventObject {
private AppEventType eventType;
public AppEvent(Application application, AppEventType eventType) {
super(application);
this.eventType = eventType;
}
public AppEventType getEventType() {
return this.eventType;
}
}
事件对象,需要持有事件源,可选持有附加信息。
这里在构造器里,除了持有数据源Application
外,还增加AppEvent
附加信息,作更进一步判断.
- 3.3 事件源
Application
一般情况下是事件源来持有监听器列表和注册注销api的,dapeng
在这里做了一个代理,注册和注销api放到来DapengContainer
中。
并且,除了持有监听器列表之外,还持有事件源列表。如下:
private List<AppListener> appListeners = new Vector<>();
private List<Application> applications = new Vector<>();
提供监听器的注册和注销api
public void registerAppListener(AppListener listener) {
this.appListeners.add(listener);
}
public void unregisterAppListener(AppListener listener) {
this.appListeners.remove(listener);
}
具体某个监听器注册自己的逻辑
public ZookeeperRegistryPlugin(Container container) {
this.container = container;
container.registerAppListener(this);
}
监听器持有了container
的引用。在构造函数里传入,并注册自己。
Why?
-
dapeng
里面有很多application
(每一个app目录下的app.jar就是一个应用服务。如app下的订单服务和会员服务,他们是分离开的。) - 之后,容器在注册了具体的application后,在application列表中加入当前的app
- 接下来,遍历application列表,然后调用监听器自己的触发事件。
public void registerApplication(Application app) {
this.applications.add(app);
this.appListeners.forEach(i -> {
try {
i.appRegistered(new AppEvent(app, AppEventType.REGISTER));
} catch (Exception e) {
LOGGER.error(" Faild to handler appEvent. listener: {}, eventType: {}", i, AppEventType.REGISTER, e.getStackTrace());
}
});
}
这样,dapeng的事件驱动模型我们就分析完了。
总结
-
dapeng
里的Contaimer
就相当于是一个Manger
管理类,维护着事件源列表和监听器列表。 - 它提供监听器和事件源来注册自己
- 它作为一个代理,每当注册了一个app后,他会触发事件,然后遍历监听器列表,来发布事件
网友评论