Java设计模式(四)——再谈观察者模式
在本系列的上一篇文章中,我们讨论了JDK对于观察者模式的一套实现。今天我们将要从另一个角度来探索Tomcat中是如何利用观察者模式加载各个组件。不过今天的任务不是解释Tomcat,所以我会单独把重点抽象出来展现如何在一个实际利用中使用Observer。
先谈一下我对观察者模式的理解。对于对象而言,观察似乎是一个主动的过程——多位观察者通过“观察”一个被观察对象状态的改变来触发一些自身的行为。是的,就设计模式来说,观察者设计的本质确实如此。可是,当引入到Java语言以后,这个“解空间”就似乎不那么“完美”了。你无法让你一个对象做到“主动”观察——轮询机制不属于今天的讨论范畴。所以,我以为称为监听器模式更加合理。
下面提出一个设计方案作为“解空间”的指导。在被观察对象(Subject)中定义一个能够注册(register)观察者(Observer)的方法和一个能够通知(notify)观察者的方法,观察者中定义一个被调用(update)的接口。
代码1.1 Subject接口:
public interface Subject {
void registerObserver(Observer ob); void removeObserver(); void notifyObserver();
}
代码1.2 Observer接口
public interface Observer {
void update();
}
对接口定义完成以后实现业务逻辑,我们在Subject的实现中假设存在一个业务接口business,这个方法的目的是实现具体的业务逻辑并调用Observer.update。
代码2.1 Observer实现:
public class ConcerteObserver implements Observer { @Override
public void update() {
System.out.println("update");
} }
代码2.2 Subject实现:
public class ConcreteSubject implements Subject {
private Observer ob; @Override
public void registerObserver(Observer ob) {
this.ob = ob;
} @Override
public void removeObserver() {
this.ob = null;
} @Override
public void notifyObserver() {
ob.update();
} public void business() {
notifyObserver();
} }
以上就是观察模式的代码逻辑,不过在实际运用的时候通常不会如此简单。下面我们来看一个相对复杂例子:利用观察者模式监听一个具有生命周期组件的各个状态。先解释一下什么是生命周期组件。在大型业务中,许多抽象的业务逻辑都具有生命周期状态。如新建、初始化、启动和停止等。不同的状态应该通知观察者触发不同的处理行为。
代码3.1 Lifecycle接口
public interface Lifecycle {
public static final int NEW_EVENT = 0;
public static final int INIT_EVENT = 1;
public static final int START_EVENT = 2;
public static final int STOP_EVENT = 3; void addListener(LifecycleListener listener); void removeListener(LifecycleListener listener); void fireLifecycleEvent(LifecycleState state);
}
Lifecycle接口提供给被观察对象实现,其中定义了4种状态事件。
代码3.2 LifecycleState枚举类
public enum LifecycleState {
NEW(Lifecycle.NEW_EVENT), INIT(Lifecycle.INIT_EVENT), START(Lifecycle.START_EVENT), STOP(Lifecycle.STOP_EVENT); private final int triggerEvent; private LifecycleState(int triggerEvent) {
this.triggerEvent = triggerEvent;
} public int getTriggerEvent() {
return triggerEvent;
} }
LifecycleState是一个枚举对象,用来约束不同的生命周期状态应该对应的事件。
代码3.3 LifecycleListener接口
public interface LifecycleListener {
void lifecycleEvent(LifecycleState state);
}
观察者的触发接口,根据LifecycleState状态实现自定义业务
代码3.4 LifeCycleBean类
public class LifeCycleBean implements Lifecycle {
private List<LifecycleListener> listeners = new ArrayList<>();
private Object locked = new Object(); @Override
public void addListener(LifecycleListener listener) {
synchronized (locked) {
listeners.add(listener);
}
} @Override
public void removeListener(LifecycleListener listener) {
synchronized (locked) {
listeners.remove(listener);
}
} @Override
public synchronized void fireLifecycleEvent(LifecycleState state) {
for (LifecycleListener listener : listeners) {
listener.lifecycleEvent(state);
}
} }
在LifeCycleBean中我们已经实现了多行程下的调用,好处是将业务逻辑和代码设计进一步分离。
代码3.5 StandardBusiness标准业务类
public class StandardBusiness extends LifeCycleBean {
private LifecycleState state = LifecycleState.NEW; public void process() {
if (state.equals(LifecycleState.NEW)) {
state = LifecycleState.INIT;
fireLifecycleEvent(state);
} else if (state.equals(LifecycleState.INIT)) {
state = LifecycleState.START;
fireLifecycleEvent(state);
} else if (state.equals(LifecycleState.START)) {
state = LifecycleState.STOP;
fireLifecycleEvent(state);
} else {
System.out.println("process end");
}
}
}
在这段业务逻辑中多次调用process方法,可以模拟生命周期的不同阶段。
代码3.6.1 InitListener类
public class InitListener implements LifecycleListener { @Override
public void lifecycleEvent(LifecycleState state) {
if(state.getTriggerEvent() == Lifecycle.INIT_EVENT) {
System.out.println("InitListener >> INIT_EVENT");
}
} }
代码3.6.2 StartListener类
public class StartListener implements LifecycleListener { @Override
public void lifecycleEvent(LifecycleState state) {
if (state.getTriggerEvent() == Lifecycle.START_EVENT) {
System.out.println("StartListener >> START_EVENT");
}
} }
代码3.6.3 StopListener类
public class StopListener implements LifecycleListener { @Override
public void lifecycleEvent(LifecycleState state) {
if (state.getTriggerEvent() == Lifecycle.STOP_EVENT) {
System.out.println("StopListener >> STOP_EVENT");
}
} }
代码3.7 测试
public class AppTest {
@Test
public void test() {
StandardBusiness business = new StandardBusiness();
business.addListener(new InitListener());
business.addListener(new StartListener());
business.addListener(new StopListener()); business.process();
business.process();
business.process();
business.process();
}
}
总结:第二个例子逻辑相对复杂但是如果能够理清思路其实与第一个例子并无太大区别。而这个就是Tomcat中对于观察者模式的运用。
最新文章
- JSON转化为JAVABEAN集合
- hadoop多次搭建后,完整总结(累死宝宝了,搭建了十多遍了)
- 微信--获取access_token
- Codeforces Round #233 (Div. 2) B. Red and Blue Balls
- jBPM4.3+ssh+会签 整合配置及完整实例
- c#中的linq一
- VPN销售管理系统一键安装包
- Javascript中setTimeout和setInterval的区别和使用
- Kernel PCA 原理和演示
- 开启SQL Server 2012的远程连接
- Aho - Corasick string matching algorithm
- zoj 3822 Domination(2014牡丹江区域赛D称号)
- main函数如何调用文件外的函数
- STL容器之优先队列
- PowerShell 语法备忘
- 游标SQL Cursor 基本用法
- Donsen法则
- [转]my97 datepicker IE9+ 故障修复方法
- Linux命令:cp (copy)复制文件或目录
- Mysql常用的锁机制
热门文章
- 201521123085 《Java程序设计》 第3周学习总结
- 聊聊JAVA中 String类为什么不可变
- 浏览器缓存机制<;转>;
- java集合系列——java集合概述(一)
- 51nod 1536不一样的猜数游戏 思路:O(n)素数筛选法。同Codeforces 576A Vasya and Petya&#39;s Game。
- 记一次坑爹的RSA旅程____快哭了555555555(来自实验吧的warmup的wp和感想)
- springmvc入门程序
- End up with More Teams UVA - 11088
- 概率图论PGM的D-Separation(D分离)
- Ionic3学习笔记(四)修改返回按钮文字、颜色