在本系列的上一篇文章中,我们讨论了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中对于观察者模式的运用。

Java设计模式(四)——再谈观察者模式的更多相关文章

  1. Java设计模式(20)观察者模式(Observer模式)

    Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循 ...

  2. Java继承之再谈构造器

    目录 Java继承之再谈构造器 初始化基类 默认构造器 带参数的构造器 子类调用父类构造器 Java继承之再谈构造器 初始化基类 前面提到,继承是子类对父类的拓展.<Thinking in Ja ...

  3. java设计模式解析(1) Observer观察者模式

      设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析( ...

  4. 【设计模式】java设计模式总述及观察者模式

    今天在准备腾讯的面试时想起来要复习一下设计模式,而刚好前几天在参加网易的在线考试的时候,也出了一道关于设计模式的选择题,主要是考察观察者模式,虽然那道题自己做对了,但觉得还是应该好好总结一下设计模式的 ...

  5. Java设计模式(三)——观察者模式和监听器

    为了实现多个模块之间的联动,最好的方法是使用观察者模式.网上介绍的资料也比较多,今天我就从另一个方面谈谈自己对观察者模式的理解.从JDK提供的支持库里,我们能够找到四个对象:Observable.Ob ...

  6. java设计模式(六)--观察者模式

    转载:设计模式(中文-文字版) 目录: 简单目标任务实现 观察者模式介绍 观察者模式代码实现 观察者模式是JDK中使用最多的模式之一,非常有用.我们也会一并介绍一对多关系,以及松耦合(对,没错,我们说 ...

  7. Java设计模式学习笔记(观察者模式)

    观察者模式说起来很简单,就是一个订报纸的模式.但是实际上这部分我觉得还是很有意思的,<Head First设计模式>里还有一些还没看完,也是因为理解的不够深吧. 观察者模式会包含两个组件: ...

  8. Java并发编程-再谈 AbstractQueuedSynchronizer 1 :独占模式

    关于AbstractQueuedSynchronizer JDK1.5之后引入了并发包java.util.concurrent,大大提高了Java程序的并发性能.关于java.util.concurr ...

  9. Java设计模式(二) 观察者模式

    观察者模式: 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会受到通知并自动更新. 1,定义事件源接口 package com.pattern.observer; pub ...

随机推荐

  1. Java第七周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 参考资料: XMind 2. 书面作业 ArrayList代码分析 1.1 解释ArrayList的contains源代码 ...

  2. 201521123090 《Java程序设计》第7周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 参考资料: XMind 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的contains源代 ...

  3. 201521123030《Java程序设计》 第2周学习总结

    本周学习总结 String常量,创建之后不能再进行修改 使用+连接字符串会产生新字符串,要大量使用重复性连接应用StringBuilder,检测字符串相等应用equal方法. 枚举类型变量的取值在一个 ...

  4. iScroll在谷歌浏览器中的问题

    通常情况下,我们会使用iScroll.js做移动端的下拉刷新和上拉加载功能,当然,还有很多其他功能. 不过,在使用iScroll的时候,在谷歌浏览器中出现不支持的情况,即,做移动的时候,出现卡顿或是每 ...

  5. AJAX应用【股票案例】

    股票案例 我们要做的是股票的案例,它能够无刷新地更新股票的数据.当鼠标移动到具体的股票中,它会显示具体的信息. 我们首先来看一下要做出来的效果: 服务器端分析 首先,从效果图我们可以看见很多股票基本信 ...

  6. 通过Excel认识POI

    1.POI是什么 Apache POI - the Java API for Microsoft Documents,顾名思义,Apache的三方包,用来操作微软office文档的,多数时候用来操作e ...

  7. ambari

    http://blog.csdn.net/ggz631047367/article/details/50491616 https://cwiki.apache.org/confluence/displ ...

  8. 深入浅出数据结构C语言版(20)——快速排序

    正如上一篇博文所说,今天我们来讨论一下所谓的"高级排序"--快速排序.首先声明,快速排序是一个典型而又"简单"的分治的递归算法. 递归的威力我们在介绍插入排序时 ...

  9. 这家IT教育公司太拼了:毕业生找不到工作就全额退学费!

    乐橙谷为了让更多的学生有工作,有高薪工作,已经决定尝试一种更刺激的游戏规则:完成课时的学员如果毕业找不到工作,公司将全额退还学费.这家公司秉承着自己的使命:以尊重的文化,敬畏的心态去努力帮助每个学生实 ...

  10. PHP中isset和empty的区别(最后总结)

    PHP的isset()函数 一般用来检测变量是否设置 格式:bool isset ( mixed var [, mixed var [, ...]] ) 功能:检测变量是否设置 返回值: 若变量不存在 ...