在本系列的上一篇文章中,我们讨论了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 {@Overridepublic void update() {System.out.println("update");}}

代码2.2 Subject实现:

public class ConcreteSubject implements Subject {private Observer ob;@Overridepublic void registerObserver(Observer ob) {this.ob = ob;}@Overridepublic void removeObserver() {this.ob = null;}@Overridepublic 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();@Overridepublic void addListener(LifecycleListener listener) {synchronized (locked) {listeners.add(listener);}}@Overridepublic void removeListener(LifecycleListener listener) {synchronized (locked) {listeners.remove(listener);}}@Overridepublic 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 {@Overridepublic 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 {@Overridepublic 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 {@Overridepublic void lifecycleEvent(LifecycleState state) {if (state.getTriggerEvent() == Lifecycle.STOP_EVENT) {System.out.println("StopListener >> STOP_EVENT");}}}

代码3.7 测试

public class AppTest {@Testpublic 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中对于观察者模式的运用。

转载于:https://www.cnblogs.com/learnhow/p/7707940.html

Java设计模式(四)——再谈观察者模式相关推荐

  1. Java函数式编程 - 再谈Stream

    Java函数式编程 - 再谈Stream 1.reduce() 前一章节说了Stream一些使用方式,Stream.reduce()也是Stream中的一个终结操作.使用起来较为复杂一些 1.1 概念 ...

  2. 【三】Java 设计模式学习记录:观察者模式

    文章目录 一.观察者模式(行为型模式) 1.1 场景 1.2 普通解决方案 1.3 观察者模式定义 1.4 观察者模式原理 二.代码实现 2.1 代码结构 2.2 上代码 2.3 扩展性 三. 框架应 ...

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

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

  4. Java设计模式-回调函数和观察者模式

    Android的框架中有非常多的地方使用了回调的模式,例如Activity的生命周期,按钮的点击事件等. 下面是回调的基本模型: public class A {private CallBack ca ...

  5. Java设计模式(四):工厂设计模式

    1. 工厂设计模式 1.1 应用场景 由于需求的变化,一个类的子类经常面临着剧烈的变化,但他却拥有比较稳定的接口.使用一种封装机制来"隔离这种易变对象的变化",工厂方法定义一个用于 ...

  6. 『设计模式』再谈麦当劳的点单模式--命令模式(Command)

    23种设计模式+额外常用设计模式汇总 (持续更新) 麦当劳,我三期设计模式拿你举例子了,私信联系我打钱!!! 概述 命令模式又称为行动(Action) 模式或交易(Transaction) 模式. 命 ...

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

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

  8. java兵临城下_再谈java事件监听机制

    java中的事件机制的参与者有3种角色: 1.event object:就是事件产生时具体的"事件",用于listener的相应的方法之中,作为参数,一般存在于listerner的 ...

  9. Java设计模式(一)观察者模式实例

    观察者模式实例 实例一:猫.狗与老鼠 假设猫是老鼠和狗的观察目标,老鼠和狗是观察者,猫叫老鼠跑,狗也跟着叫,使用观察者模式描述该过程. 类图: 抽象观察者(MyObserver) public int ...

  10. Java设计模式之再从[暗黑破坏神装备镶嵌宝石系统]分析装饰(Decorator)模式

    在暗黑破坏神等RPG游戏中,会遇到如下的一些场景:我有一把很普通的武器,我通过给它"注入魔法力量"."镶嵌宝石",来使得它拥有一些攻击特效:例如,一把普通长剑, ...

最新文章

  1. ASP.NET MVC 音乐商店 - 9. 注册和结账
  2. MyBatis中传递数组参数和List参数时if-test判空和判断长度的写法
  3. 帮人取款每百元抽10元回扣,最终涉嫌诈骗罪被批捕
  4. FreeSql (十五)查询数据
  5. compat包_使用Compat Patchers,API的稳定性既便宜又容易!
  6. rtmp服务器 协议之同步
  7. 在Sharepoint Designer 2007 中加入定制的工作流动作
  8. OpenGL shader 中关于顶点坐标值的思考
  9. .net面试中常被面试官问到的问题
  10. Graphics.DrawLine 方法
  11. python矩形法求定积分_c程序用矩形法编一个通用函数求定积分0到1区间sinx,cosx,e的x次方,1+x,2x+3,(x*x)+1,e的x次方+1,(1+X)*(1+X),x*x*x...
  12. php获取ip所有方式,php获取用户(客户端)真实IP地址的三种方法
  13. 便携式手持 频谱分析仪_便携式频谱分析仪
  14. Linux·串口编程
  15. Uni-app开发App和插件以后如何开通广告盈利:uni-AD
  16. 传奇人物《周兴和》书连载30 成功背后的陷阱
  17. Android客户端与服务器端socket通讯
  18. 安卓微信浏览器唤起系统内部浏览器
  19. linux查看主板最大内存容量,Linux 查看内存插槽数、最大容量的方法
  20. 教程分享:Python预测票房数据分析视频课程

热门文章

  1. 大学c语言作业网站,西北农林科技大学c语言作业
  2. 数据结构--图 记事本
  3. Windows核心编程_调用控制台窗口
  4. [解题报告]Bees' ancestors
  5. Windows 上安装 Scala
  6. R语言实战-读书笔记整理
  7. (删)Java线程同步实现二:Lock锁和Condition
  8. Android各版本代号、版本号、API/NDK级别、发布时间及市场份额
  9. Python 2.5.1 切片
  10. ABAP - 3D Graphs with SAP