门面设计模式在 Tomcat 中有多处使用,在 Request 和 Response 对象封装中、Standard Wrapper 到 ServletConfig 封装中、ApplicationContext 到 ServletContext 封装中等都用到了这种设计模式。程序员
这么多场合都用到了这种设计模式,那这种设计模式究竟能有什么做用呢?顾名思义,就是将一个东西封装成一个门面好与人家更容易进行交流,就像一个国家的外交部同样。面试
这种设计模式主要用在一个大的系统中有多个子系统组成时,这多个子系统确定要涉及到相互通讯,可是每一个子系统又不能将本身的内部数据过多的暴露给其它系统,否则就没有必要划分子系统了。每一个子系统都会设计一个门面,把别的系统感兴趣的数据封装起来,经过这个门面来进行访问。这就是门面设计模式存在的意义。数据库
门面设计模式示意图以下:设计模式
图 1. 门面示意图tomcat
Client 只能访问到 Façade 中提供的数据是门面设计模式的关键,至于 Client 如何访问 Façade 和 Subsystem 如何提供 Façade 门面设计模式并无规定死。服务器
Tomcat 中门面设计模式使用的不少,由于 Tomcat 中有不少不一样组件,每一个组件要相互交互数据,用门面模式隔离数据是个很好的方法。微信
下面是 Request 上使用的门面设计模式:架构
图 2. Request 的门面设计模式类图app
从图中能够看出 HttpRequestFacade 类封装了 HttpRequest 接口可以提供数据,经过 HttpRequestFacade 访问到的数据都被代理到 HttpRequest 中,一般被封装的对象都被设为 Private 或者 Protected 访问修饰,以防止在 Façade 中被直接访问。分布式
这种设计模式也是经常使用的设计方法一般也叫发布 - 订阅模式,也就是事件监听机制,一般在某个事件发生的先后会触发一些操做。
观察者模式原理也很简单,就是你在作事的时候旁边总有一我的在盯着你,当你作的事情是它感兴趣的时候,它就会跟着作另一些事情。可是盯着你的人必需要到你那去登记,否则你没法通知它。观察者模式一般包含下面这几个角色:
Tomcat 中观察者模式也有多处使用,前面讲的控制组件生命周期的 Lifecycle 就是这种模式的体现,还有对 Servlet 实例的建立、Session 的管理、Container 等都是一样的原理。下面主要看一下 Lifecycle 的具体实现。
Lifecycle 的观察者模式结构图:
图 3. Lifecycle 的观察者模式结构图
上面的结构图中,LifecycleListener 表明的是抽象观察者,它定义一个 lifecycleEvent 方法,这个方法就是当主题变化时要执行的方法。 ServerLifecycleListener 表明的是具体的观察者,它实现了 LifecycleListener 接口的方法,就是这个具体的观察者具体的实现方式。Lifecycle 接口表明的是抽象主题,它定义了管理观察者的方法和它要所作的其它方法。而 StandardServer 表明的是具体主题,它实现了抽象主题的全部方法。这里 Tomcat 对观察者作了扩展,增长了另外两个类:LifecycleSupport、LifecycleEvent,它们做为辅助类扩展了观察者的功能。LifecycleEvent 使得能够定义事件类别,不一样的事件可区别处理,更加灵活。LifecycleSupport 类代理了主题对多观察者的管理,将这个管理抽出来统一实现,之后若是修改只要修改 LifecycleSupport 类就能够了,不须要去修改全部具体主题,由于全部具体主题的对观察者的操做都被代理给 LifecycleSupport 类了。这能够认为是观察者模式的改进版。
LifecycleSupport 调用观察者的方法代码以下:
清单 1. LifecycleSupport 中的 fireLifecycleEvent 方法
1 2 3 4 5 6 7 8 9 |
|
主题是怎么通知观察者呢?看下面代码:
清单 2. 容器中的 start 方法
1 2 3 4 5 6 7 8 9 10 11 12 |
|
前面把 Tomcat 中两个核心组件 Connector 和 Container,比做一对夫妻。男的将接受过来的请求以命令的方式交给女主人。对应到 Connector 和 Container,Connector 也是经过命令模式调用 Container 的。
命令模式主要做用就是封装命令,把发出命令的责任和执行命令的责任分开。也是一种功能的分工。不一样的模块能够对同一个命令作出不一样解释。
下面是命令模式一般包含下面几个角色:
Tomcat 中命令模式在 Connector 和 Container 组件之间有体现,Tomcat 做为一个应用服务器,无疑会接受到不少请求,如何分配和执行这些请求是必须的功能。
下面看一下 Tomcat 是如何实现命令模式的,下面是 Tomcat 命令模式的结构图:
图 4. Tomcat 命令模式的结构图
Connector 做为抽象请求者,HttpConnector 做为具体请求者。HttpProcessor 做为命令。Container 做为命令的抽象接受者,ContainerBase 做为具体的接受者。客户端就是应用服务器 Server 组件了。Server 首先建立命令请求者 HttpConnector 对象,而后建立命令 HttpProcessor 命令对象。再把命令对象交给命令接受者 ContainerBase 容器来处理命令。命令的最终是被 Tomcat 的 Container 执行的。命令能够以队列的方式进来,Container 也能够以不一样的方式来处理请求,如 HTTP1.0 协议和 HTTP1.1 的处理方式就会不一样。
Tomcat 中一个最容易发现的设计模式就是责任链模式,这个设计模式也是 Tomcat 中 Container 设计的基础,整个容器的就是经过一个链链接在一块儿,这个链一直将请求正确的传递给最终处理请求的那个 Servlet。
责任链模式,就是不少对象有每一个对象对其下家的引用而链接起来造成一条链,请求在这条链上传递,直到链上的某个对象处理此请求,或者每一个对象均可以处理请求,并传给下一家,直到最终链上每一个对象都处理完。这样能够不影响客户端而可以在链上增长任意的处理节点。
一般责任链模式包含下面几个角色:
在 tomcat 中这种设计模式几乎被完整的使用,tomcat 的容器设置就是责任链模式,从 Engine 到 Host 再到 Context 一直到 Wrapper 都是经过一个链传递请求。
Tomcat 中责任链模式的类结构图以下:
图 5. Tomcat 责任链模式的结构图
上图基本描述了四个子容器使用责任链模式的类结构图,对应的责任链模式的角色,Container 扮演抽象处理者角色,具体处理者由 StandardEngine 等子容器扮演。与标准的责任链不一样的是,这里引入了 Pipeline 和 Valve 接口。他们有什么做用呢?
实际上 Pipeline 和 Valve 是扩展了这个链的功能,使得在链往下传递过程当中,可以接受外界的干预。Pipeline 就是链接每一个子容器的管子,里面传递的 Request 和 Response 对象比如管子里流的水,而 Valve 就是这个管子上开的一个个小口子,让你有机会可以接触到里面的水,作一些额外的事情。
为了防止水被引出来而不能流到下一个容器中,每一段管子最后总有一个节点保证它必定能流到下一个子容器,因此每一个容器都有一个 StandardXXXValve。只要涉及到这种有链式是处理流程这是一个很是值得借鉴的模式。
微信公众号【Java技术江湖】一位阿里 Java 工程师的技术小站。(关注公众号后回复”Java“便可领取 Java基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送做者原创的Java学习指南、Java程序员面试指南等干货资源)