外观模式
外观模式是对象的结构模式,外部与一个子系统的通信必须通过一个统一的外观对象进行。外观模式是一个高层次的接口,使得子系统更易于使用。
医院的例子
现代的软件系统都是比较复杂的。假如把医院比作一个子系统,按照部门职能,这个系统划分为挂号、门诊、划价、化验、收费、取药等。看病的人要与这些部门打交道,就如同一个子系统的客户端与一个子系统的各个类打交道一样,不是一件容易的事。
解决这种不便的方法便是引入外观模式,医院可以设置一个接待员的位置,由接待员负责代为挂号、划价、缴费、取药等。病人只需要接触接待员,由接待员与各个部门打交道。
外观模式的结构
外观模式的结构可以这么表示:
这个图中,体现了两种角色:
1、外观角色
客户端调用这个角色的方法。此角色知晓相关的子系统的功能和责任,正常情况下,本角色会将所有从客户端发来的请求委派到响应的子系统中
2、子系统角色
可以同时有一个或多个子系统,每个子系统都不是一个单独的类,而是一个类的集合。每个子系统都可以被客户端直接调用,或者被外观角色直接调用。子系统并不知道外观角色的存在,对于子系统而言,外观仅仅是另外一个客户端而已
外观模式示例
模拟三个子系统 ModuleA、ModuleB、ModuleC:
- public class ModuleA {
- public void testA() {
- System.out.println("调用Module中的testA方法");
- }
- }
- public class ModuleB {
- public void testB() {
- System.out.println("调用Module中的testB方法");
- }
- }
- public class ModuleC {
- public void testC() {
- System.out.println("调用Module中的testC方法");
- }
- }
模拟一个外观对象:
- public class Facade {
- public void test() {
- ModuleA ma = new ModuleA();
- ma.testA();
- ModuleB mb = new ModuleB();
- mb.testB();
- ModuleC mc = new ModuleC();
- mc.testC();
- }
- }
写一个客户端调用一下外观角色:
- public static void main(String[] args) {
- Facade facade = new Facade();
- facade.test();
- }
运行结果很明显:
- 调用Module中的testA方法调用Module中的testB方法调用Module中的testC方法
这样,客户端不需要亲自调用子系统的 A、B、C 模块了,也不需要知道内部系统的实现细节,甚至不需要知道模块 A、模块 B、模块 C 的存在,只需要和 Facade 类交互就好了,从而更好地实现了客户端和子系统中的三个模块的解耦,让客户端更容易地使用子系统。
另外,定义一个外观类还可以有效地屏蔽内部的细节。因为子系统中有一些方法,是模块之间相互交互用的,并不需要外部调用。如果直接调用子系统的类方法,会出现一些不需要客户端知道的方法,这样既暴露了内部细节,又让客户端模迷惑。外观类就不一样了,可以只给客户端提供那些子系统给外部使用的方法。
外观模式在 Java 中的应用及解读
Tomcat 中有很多场景都使用到了外观模式,因为 Tomcat 中有很多不同的组件,每个组件需要相互通信,但又不能将自己内部数据过多地暴露给其他组件。用外观模式隔离数据是个很好的方法,比如 Request 上使用外观模式:
比如 Servlet,doGet 和 doPost 方法,参数类型是接口 HttpServletRequest 和接口 HttpServletResponse,那么 Tomcat 中传递过来的真实类型到底是什么呢?
有过对 Java web 项目 Debug 经验的肯定会发现,在真正调用 Servlet 前,会经过很多 Tomcat 方法。反编译一下 javaee.jar 包就会看到,传递给 Tomcat 的 request 和 response 的真正类型是:
看到返回的都是一个 Facade 类。因为 Request 类中很多方法都是组件内部之间交互用的,比如 setComet、setReuqestedSessionId 等方法,这些方法并不对外公开,但又必须设置为 public,因为还要和内部组件交互使用。最好的解决方法就是通过使用一个 Facade 类,屏蔽掉内部组件之间交互的方法,只提供外部程序要使用的方法。
如果不使用 Facade,直接传递的是 HttpServletRequest 和 HttpServletResponse,那么熟悉容器内部运作的开发者可以分别把 ServletRequest 和 ServletResponse 向下转型为 HttpServletRequest 和 HttpServletResponse,这样就有安全性的问题了。
外观模式的优点
外观模式有如下几个优点:
1、松散耦合
外观模式松散了客户端和子系统的耦合关系,让子系统内部的模块能更容易扩展和维护
2、简单易用
客户端不需要了解系统内部的实现,也不需要和众多子系统内部的模块交互,只需要和外观类交互就可以了
3、更好地划分层次
通过合理使用 Facade,可以帮助我们更好地划分层次。有些方法是系统对内的,有些方法是对外的,把需要暴露给外部的功能集中到 Facade 中,这样既方便客户端使用,也很好地隐藏了内部的细节
就爱阅读 www.92to.com 网友整理上传, 为您提供最全的知识大全, 期待您的分享,转载请注明出处。
来源: