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 ...
随机推荐
- 学号:201521123116 《java程序设计》第六周学习总结
1. 本章学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 2.书面作业 1.1.Object对象中的clone方法是 ...
- 201521123012 《Java程序设计》第六周学习总结
##1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. -注1:关键词与内容不求多,但概念之间的联系要清晰,内 ...
- java第十三次作业
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相内关容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...
- POJ-2299 Ultra-QuickSort (树状数组,离散化,C++)
Problem Description In this problem, you have to analyze a particular sorting algorithm. The algorit ...
- 谈一谈最近学了一段时间的node.js
官方说明 1.NodeJS宣称其目标是“旨在提供一种简单的构建可伸缩网络程序的方法”. 2.node是一个基于Chrome V8引擎进行代码解释的.轻量.可伸缩的具有事件驱动和非阻塞I/O机制的js运 ...
- Struts 2.5 Filter mapping specifies an unknown filter name [struts2]
问题一:java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start ...
- Ubuntu16.04安装piwik3.0.1
1.安装PHP环境 sudo apt-get install php7.0-fpm 2.下载piwik3.0.1 https://piwik.org/download/ 下载后解压到/var/ww ...
- python进阶之Socket 网络编程
一:网络编程介绍 自从互联网诞生以来,现在基本上所有的程序都是网络程序,很少有单机版的程序了. 计算机网络就是把各个计算机连接到一起,让网络中的计算机可以互相通信.网络编程就是如何在程序中实现两 ...
- mvc一对多模型表单的快速构建
功能需求描述 Q:在实际的开发中,经常会遇到一个模型中包含有多个条目的表单.如何将数据提交到后台? A: 以数组的形式提交到后台就Ok了(真的那么简单么,如果再嵌套一层呢?) A2:拆分多个模型,映射 ...
- ArrayList ConcurrentModificationException
1.ConcurrentModificationException ConcurrentModificationException 出现在使用 ForEach遍历,迭代器遍历的同时,进行删除,增加出现 ...