在这一篇中,看下观察者模式的应用。首先来看下观察者模式的概念:观察者模式是一种一对多的关系,多个观察者对象同时关注一个主题对象。观察者模式中有主题对象和观察者对象,我们可以把球赛比作一个观察者模型,那么球赛就是主题对象,观众就是观察者对象。以下通过java语言对观察者,java.util.Observable的应用实现,观察者在tomcat源代码中的应用,三个部分来阐述观察者模式。
一. java语言中的观察者模式
通过java.util.Observable,首先来看下其源代码。
//观察者接口
public interface Observer {
void update(Observable o, Object arg);
}
//主题对象
public class Observable {
private boolean changed = false;//状态变量
//维护观察者对象的集合
private Vector obs;
public Observable() {
obs = new Vector();
}
//将观察者加入到集合中
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
//从集合中删除观察者
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
//通知
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed) return;
arrLocal = obs.toArray();//将结合转化成数组
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);//观察者作出状态改变的操作
}
//状态的几个相关方法
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
二.java.util.Observable的应用实现
上一部分是java源代码中对于观察者模式的实现,对代码有注释。如果不明白的话,可以结合下面的一个例子来看,就应该很清楚了。个人觉得以下的例子(来自网上)比《设计与模式》一书中的例子更直观些,商品为主题对象,对于商品的价格和名称的改变有相应的观察者。
主题对象
public class Product extends Observable{
private String name;
private float price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
//设置观察点(changed=true )
setChanged();
//观察者作出相应的改变
notifyObservers(name);
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
//设置观察点,同上
setChanged();
notifyObservers(price);
}
}
观察者对象
//商品名称观察者类
public class NameObserver implements Observer{
private String name = "";
//源代码中对应((Observer)arrLocal[i]).update(this, arg)
public void update(Observable ob, Object arg) {
if(arg instanceof String){
name = (String)arg;
System.out.println("name has been changed to:"+name);
}
}
}
//价格观察者类
public class PriceObserver implements Observer{
private float price;
//同上
public void update(Observable ob, Object arg) {
if(arg instanceof Float){
price = (Float)arg;
System.out.println("name has been changed to:"+price);
}
}
}
运行看下效果
public static void main(String[] args) {
Product p1 = new Product();
NameObserver nameObserver = new NameObserver();
PriceObserver priceObserver = new PriceObserver();
p1.addObserver(nameObserver);
p1.addObserver(priceObserver);
p1.setName("苹果");
p1.setPrice(8);
p1.setName("香蕉");
}
三. tomcat中观察者的实现
结合源代码的分析以及一个实例,应该对于观察者模式有一定的理解了,接下来看下在tomcat的源代码中的使用。
(1)主题接口LifeCycle,在其中定义了状态变量init,start…等的状态,看下源代码对于该接口的定义。
//增加观察者
public addLifecycleListener(LifecycleListener listener);
//获取所有的观察者
public LifecycleListener[] findLifecycleListeners();
//移除观察者
public void removeLifecycleListener(LifecycleListener listener);
//其他2个方法
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
(2)观察者接口 LifecycleListener的定义
//主题变化时候,要执行的方法
public void lifecycleEvent(LifecycleEvent event);
(3) 有大量类实现了主题LifeCycle接口,作为取其中的StandardServer来分析,看下是怎么用的。
由于在StandardServer中用到了LifeCycleSupport,所以先分析下该类。
public final class LifeCycleSupport{
//构造器
public LifeCycleSupport (Lifecycle lifecycle) {
super();
this.lifecycle = lifecycle;
}
//存储观察者的数组,看Lifecycle就会发现。里面有一个findLifecycleListeners获取数组,但是没有定义数组变量。
private LifecycleListener listeners[] = new LifecycleListener[0];
//将观察者对象放入到数组中,此处定义直接每次增加的时候,定义一个数目加1的数据。是出于性能的考虑,这种方式可以在编程中运用。在tomcat中可以看到大量类似的编程方式有些是用System.arraycopy来处理.
public void addLifecycleListener(LifecycleListener listener) {
synchronized (listenersLock) {
LifecycleListener results[] =
new LifecycleListener[listeners.length + 1];
for (int i = 0; i < listeners.length; i++)
results[i] = listeners[i];
results[listeners.length] = listener;
listeners = results;
}
}
public LifecycleListener[] findLifecycleListeners() {
return listeners;
}
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
public void fireLifecycleEvent(String type, Object data) {
if (Lifecycle.INIT_EVENT.equals(type)) {
state = "INITIALIZED";
}//此处省略部分else if 语句
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
LifecycleListener interested[] = listeners;
for (int i = 0; i < interested.length; i++)
interested[i].lifecycleEvent(event);//有改变后观察者进行处理
}
}
(4)看了LifeCycleSupport的实现,再看下StandardServer中的实现就很清楚了。该类中lifecycle的方法全部是调用LifeCycleSupport。这里是对观察者之上有进一步的处理。
public final class StandardServer
implements LifeCycle, Server, MBeanRegistration
//这里看下LifeCycle接口中的几个方法的实现
private LifeCycleSupport lifeCycle = new LifeCycleSupport(this);
public void addLifeCycleListener(LifeCycleListener listener) {
lifeCycle.addLifeCycleListener(listener);
}
public LifecycleListener[] findLifecycleListeners() {
return lifecycle.findLifecycleListeners();
}
public void start() throws LifecycleException {
// Validate and update our current component state
if (started) {
log.debug(sm.getString("standardServer.start.started"));
return;
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Start our defined Services
synchronized (services) {
for (int i = 0; i < services.length; i++) {
if (services[i] instanceof Lifecycle)
((Lifecycle) services[i]).start();
}
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
(5)LifecycleEvent这个类,是将数据封装在一个对象中。
在org.apache.catalina.mbeans.ServerLifecycleListener中可以看到,对于观察者在不同状态下的实现代码。
文字编译器不好用,莫名奇妙的多了很多空的java代码框。
分享到:
相关推荐
【标签】"tomcat源码分析"表明整个资料集专注于Tomcat的源代码级探索,适合于开发者或运维人员深入了解服务器的底层实现。 【文件名称列表】中的每个文档都对应一个特定主题: 1. "Tomcat处理HTTP请求源码分析.doc...
《Tomcat6源码分析——深入理解Web服务器的运行机制》 Tomcat6作为Apache软件基金会的Jakarta项目的一部分,是一款广泛使用的Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,为开发和部署...
### Tomcat架构的源码分析 #### 一、Tomcat的架构概述 Tomcat作为一款广泛使用的开源Java Servlet容器,其内部架构设计简洁而高效。本文档将对Tomcat的架构进行详细介绍,并从源码层面深入分析其核心组成部分。...
Tomcat源码剖析 : 整体架构 层层分析 源码解析 架构分析 (Http服务器功能:Socket通信(TCP/IP)、解析Http报文 Servlet容器功能:有很多Servlet(自带系统级Servlet+自定义Servlet),Servlet处理具体的业务逻辑...
【TOMCAT源码分析(启动框架)】 Tomcat是一款广泛应用的开源Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,为Web应用程序提供了运行环境。本篇文章将深入探讨Tomcat的系统框架及其启动流程...
tomcat的基础脚本分析 tomcat的源码启动分析 tomcat的web应用启动分析 tomcat的socket分析 tomcat的cocket与容器对接时序分析
Apache Tomcat源码分析 Apache Tomcat是一款广泛应用的开源Java Servlet容器,它是Java EE Web应用程序的标准实现。Tomcat源码的深入理解对于Java Web开发者来说是至关重要的,它可以帮助我们了解HTTP服务器的工作...
【标题】"Tomcat源码分析" 在深入探讨Tomcat源码之前,首先需要了解Tomcat是什么。Tomcat是一款开源的、基于Java的Web应用服务器,由Apache软件基金会开发。它实现了Java Servlet和JavaServer Pages(JSP)规范,...
对 NIO 模式,请求的流程描述的很详细。值得去仔细的研究。
tomcat源码分析,tomcat原理分析,底层机制,一些源代码等等
《Tomcat源码分析1——服务启动与架构详解》 Tomcat,作为一款广泛应用的开源Java Servlet容器,其内部架构和启动流程对于深入理解和优化Web应用程序至关重要。本文将重点解析Tomcat启动时的关键步骤和核心组件,...
《深入理解Tomcat源码分析1:Connector配置详解》 Tomcat,作为广泛使用的Java Servlet容器,其核心组件之一就是Connector,它负责处理Web服务器与客户端之间的通信。本篇文章将详细探讨Tomcat Connector的种类、...
2. **Apache Ant**:Ant是一个Java库和命令行工具,用于构建Java项目,它是编译Tomcat源码的必备工具。Ant的jar文件包含了构建脚本执行所需的所有类和方法。 3. **Apache Commons**:Apache Commons是Apache软件...
Apache Tomcat 8.5.23 源码分析 Apache Tomcat 是一个开源的、免费的Web服务器和Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,是开发和部署Java Web应用的重要平台。深入理解Tomcat的源码有助...
源码分析是提升开发者对服务器内部运作机制理解的重要途径,尤其对于Tomcat这样的核心组件,源码的学习能够帮助我们更深入地理解Web应用的部署、运行以及性能优化。 首先,我们要了解Tomcat的架构。Tomcat7基于...