最近在研究tomcat,手上有一份尚硅谷的tomcat设计模式的资料,翻开看了看个人觉得写得还是很好的。设计模式一般都是在有一定的代理积累之后才能用到的相关的这种解决方案。常用的一共有23种设计模式,具体的可以去看看我老早自己整理的设计模式里面那些blog。
Tomcat 中运用的许多经典设计模式,如模版模式、工厂模式和单例模式等。通过学习它们的实践运用能给我们以后的软件设计起到一定的借鉴作用。这里主要整理4种:
- 1. 门面设计模式
- 门面设计模式的原理
上面这些主要是讲到tomcat里面用于隔离数据,提高安全性这块。其实门面设计模式还可以用来融合组件,就是说我可以把多个功能有关联的组件集中整理到一个门面中,这样子就不用每次繁琐的调用多个组件了,直接去访问门面掉里面的方法就好了。
Client 只能访问到 Facade 中提供的数据是门面设计模式的关键,至于 Client 如何访问 Facade 和 Subsystem 如何提供 Façade 门面设计模式并没有规定死。
- Tomcat 的门面设计模式示例
- 2. 观察者设计模式
这种设计模式也是常用的设计方法通常也叫发布 - 订阅模式,也就是事件监听机制,通常在某个事件发生的前后会触发一些操作。
- 观察者模式的原理
观察者模式原理也很简单,就是你在做事的时候旁边总有一个人在盯着你,当你做的事情是它感兴趣的时候,它就会跟着做另外一些事情。但是盯着你的人必须要到你那去登记,不然你无法通知它。
Subject 就是抽象主题:它负责管理所有观察者的引用,同时定义主要的事件操作。
ConcreteSubject 具体主题:它实现了抽象主题的所有定义的接口,当自己发生变化时,会通知所有观察者。Observer 观察者:监听主题发生变化相应的操作接口。
- Tomcat 的观察者模式示例
LifecycleSupport 调用观察者的方法代码如下:
//LifecycleSupport 中的 fireLifecycleEvent 方法 public void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(lifecycle, type, data); LifecycleListener interested[] = null; synchronized (listeners) { interested = (LifecycleListener[]) listeners.clone(); } for (int i = 0; i < interested.length; i++) interested[i].lifecycleEvent(event); }
主题是怎么通知观察者呢?代码如下:
//容器中的 start 方法 public void start() throws LifecycleException { lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); lifecycle.fireLifecycleEvent(START_EVENT, null); started = true; synchronized (services) { for (int i = 0; i < services.length; i++) { if (services[i] instanceof Lifecycle) ((Lifecycle) services[i]).start(); } } lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null); }
3. 命令设计模式
前面把 Tomcat 中两个核心组件 Connector 和 Container,比作一对夫妻。男的将接受过来的请求以命令的方式交给女主人。对应到 Connector 和 Container, Connector 也是通过命令模式调用Container 的。
- 命令模式的原理
命令模式主要作用就是封装命令,把发出命令的责任和执行命令的责任分开。也是一种功能的分工。不同的模块可以对同一个命令做出不同解释。
Client:创建一个命令,并决定接受者
Command 命令:命令接口定义一个抽象方法
ConcreteCommand:具体命令,负责调用接受者的相应操作
Invoker 请求者:负责调用命令对象执行请求
Receiver 接受者:负责具体实施和执行一次请求
- Tomcat 中的命令模式的示例
下面看一下 Tomcat 是如何实现命令模式的,Connector 作为抽象请求者, HttpConnector 作为具体请求者。HttpProcessor 作为命令。 Container 作为命令的抽象接受者,ContainerBase 作为具体的接受者。客户端就是应用服务器 Server组件了。Server 首先创建命令请求者 HttpConnector 对象,然后创建命令 HttpProcessor 命令对象。再把命令对象交给命令接受者
ContainerBase 容器来处理命令。命令的最终是被 Tomcat 的Container 执行的。命令可以以队列的方式进来, Container 也可以以不同的方式来处理请求,如 HTTP1.0 协议和 HTTP1.1 的处理方式就会不同。
- 4. 责任链模式
- 责任链模式的原理
通常责任链模式包含下面几个角色:
Handler(抽象处理者):定义一个处理请求的接口
ConcreteHandler(具体处理者):处理请求的具体类,或者传给下家
- Tomcat 中责任链模式示例
Wrapper 都是通过一个链传递请求。这种模式比较简单的,我以前也没有遇见过,链式来传递请求?大致的理解下好了,不是很难,个人觉得也没太大难度的。
Container 扮演抽象处理者角色,具体处理者由StandardEngine 等子容器扮演。与标准的责任链不同的是,这里引入了Pipeline 和 Valve 接口。他们有什么作用呢?实际上 Pipeline 和 Valve 是扩展了这个链的功能,使得在链往下传递过程中,能够接受外界的干预。 Pipeline 就是连接每个子容器的管子,里面传递的 Request 和 Response 对象好比管子里流的水,而 Valve 就是这个管子上开的一个个小口子,让你有机会能够接触到里面的水,做一些额外的事情。为了防止水被引出来而不能流到下一个容器中,每一段管子最后总有一个节点保证它一定能流到下一个子容器,所以每个容器都有一个 StandardXXXValve。只要涉及到这种有链式是处理流程这是一个非常值得借鉴的模式。