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中对于观察者模式的运用。
Java设计模式(四)——再谈观察者模式的更多相关文章
- Java设计模式(20)观察者模式(Observer模式)
Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循 ...
- Java继承之再谈构造器
目录 Java继承之再谈构造器 初始化基类 默认构造器 带参数的构造器 子类调用父类构造器 Java继承之再谈构造器 初始化基类 前面提到,继承是子类对父类的拓展.<Thinking in Ja ...
- java设计模式解析(1) Observer观察者模式
设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析( ...
- 【设计模式】java设计模式总述及观察者模式
今天在准备腾讯的面试时想起来要复习一下设计模式,而刚好前几天在参加网易的在线考试的时候,也出了一道关于设计模式的选择题,主要是考察观察者模式,虽然那道题自己做对了,但觉得还是应该好好总结一下设计模式的 ...
- Java设计模式(三)——观察者模式和监听器
为了实现多个模块之间的联动,最好的方法是使用观察者模式.网上介绍的资料也比较多,今天我就从另一个方面谈谈自己对观察者模式的理解.从JDK提供的支持库里,我们能够找到四个对象:Observable.Ob ...
- java设计模式(六)--观察者模式
转载:设计模式(中文-文字版) 目录: 简单目标任务实现 观察者模式介绍 观察者模式代码实现 观察者模式是JDK中使用最多的模式之一,非常有用.我们也会一并介绍一对多关系,以及松耦合(对,没错,我们说 ...
- Java设计模式学习笔记(观察者模式)
观察者模式说起来很简单,就是一个订报纸的模式.但是实际上这部分我觉得还是很有意思的,<Head First设计模式>里还有一些还没看完,也是因为理解的不够深吧. 观察者模式会包含两个组件: ...
- Java并发编程-再谈 AbstractQueuedSynchronizer 1 :独占模式
关于AbstractQueuedSynchronizer JDK1.5之后引入了并发包java.util.concurrent,大大提高了Java程序的并发性能.关于java.util.concurr ...
- Java设计模式(二) 观察者模式
观察者模式: 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会受到通知并自动更新. 1,定义事件源接口 package com.pattern.observer; pub ...
随机推荐
- 201521123017 《Java程序设计》第2周学习总结
1. 本章学习总结 (1)Arrays和String的用法及其函数的一些运用,例如sort函数,输入多个数字,用Arrays.sort(数组名),对数组中的元素排序,从小到大,与冒泡法对比更加方便使用 ...
- 社工数据搜索引擎搭建 - Build Social Engineer Evildata Search Engine
如何设计搭建一个社工库 从初起设计一个社工库,到现在的Beta,前前后后零零整整花了不下一个月的时间,林林总总记录下来,留给需要之人 泄露数据库格式不一,长相奇葩,因需将用户名.密码.邮箱.哈希等信息 ...
- 201521123053《Java程序设计》第十二周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 一些有关流与文件的知识点: 1. 字节缓冲流: BufferedInputStream(FileInputSt ...
- 201521123113《Java程序设计》第12周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...
- [js高手之路]Node.js+jade+mongodb+mongoose实现爬虫分离入库与生成静态文件
接着这篇文章[js高手之路]Node.js+jade抓取博客所有文章生成静态html文件继续,在这篇文章中实现了采集与静态文件的生成,在实际的采集项目中, 应该是先入库再选择性的生成静态文件.那么我选 ...
- postman安装使用教程---图文讲解
一.安装postman 1,安装包安装 官网下载地址:https://www.getpostman.com 选择好对应的版本下载,下载完后直接安装 2,插件包安装 可以在谷歌的应用商店里面找到,或者在 ...
- oracle pl/sql 分页
一.无返回值的存储过程 古人云:欲速则不达,为了让大家伙比较容易接受分页过程编写,我还是从简单到复杂,循序渐进的给大家讲解.首先是掌握最简单的存储过程,无返回值的存储过程. 案例:现有一张表book, ...
- AngularJS的$rootScope和$scope联系和区别
scope是html和单个controller之间的桥梁,数据绑定就靠他了. rootscope是各个controller中scope的桥梁.用rootscope定义的值,可以在各个controlle ...
- 01.python基础知识_01
一.编译型语言和解释型语言的区别是什么? 1.编译型语言将源程序全部编译成机器码,并把结果保存为二进制文件.运行时,直接使用编译好的文件即可 2.解释型语言只在执行程序时,才一条一条的解释成机器语言给 ...
- SpringMVC学习笔记(二)
一.导航 复杂类型的参数绑定 校验 异常处理 图片上传 json交互 拦截器 二.复杂类型参数绑定 ①.包装类型的pojo参数绑定 使用场景:实现商品查询条件传入. 实现方法:>通过添加Http ...