《JAVA设计模式》之外观模式(Facade)
在阎宏博士的《JAVA与模式》一书中开头是这样描述门面(Facade)模式的:
门面模式是对象的结构模式,外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。
医院的例子
现代的软件系统都是比较复杂的,设计师处理复杂系统的一个常见方法便是将其“分而治之”,把一个系统划分为几个较小的子系统。如果把医院作为一个子系统,按照部门职能,这个系统可以划分为挂号、门诊、划价、化验、收费、取药等。看病的病人要与这些部门打交道,就如同一个子系统的客户端与一个子系统的各个类打交道一样,不是一件容易的事情。
首先病人必须先挂号,然后门诊。如果医生要求化验,病人必须首先划价,然后缴费,才可以到化验部门做化验。化验后再回到门诊室。
上图描述的是病人在医院里的体验,图中的方框代表医院。
解决这种不便的方法便是引进门面模式,医院可以设置一个接待员的位置,由接待员负责代为挂号、划价、缴费、取药等。这个接待员就是门面模式的体现,病人只接触接待员,由接待员与各个部门打交道。
门面模式的结构
门面模式没有一个一般化的类图描述,最好的描述方法实际上就是以一个例子说明。
由于门面模式的结构图过于抽象,因此把它稍稍具体点。假设子系统内有三个模块,分别是ModuleA、ModuleB和ModuleC,它们分别有一个示例方法,那么此时示例的整体结构图如下:
在这个对象图中,出现了两个角色:
● 门面(Facade)角色 :客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
● 子系统(SubSystem)角色 :可以同时有一个或者多个子系统。每个子系统都不是一个单独的类,而是一个类的集合(如上面的子系统就是由ModuleA、ModuleB、ModuleC三个类组合而成)。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。
源代码
子系统角色中的类:
public class ModuleA {
//示意方法
public void testA(){
System.out.println("调用ModuleA中的testA方法");
}
}
public class ModuleB {
//示意方法
public void testB(){
System.out.println("调用ModuleB中的testB方法");
}
}
public class ModuleC {
//示意方法
public void testC(){
System.out.println("调用ModuleC中的testC方法");
}
}
门面角色类:
public class Facade {
//示意方法,满足客户端需要的功能
public void test(){
ModuleA a = new ModuleA();
a.testA();
ModuleB b = new ModuleB();
b.testB();
ModuleC c = new ModuleC();
c.testC();
}
}
客户端角色类:
public class Client { public static void main(String[] args) { Facade facade = new Facade();
facade.test();
} }
Facade类其实相当于A、B、C模块的外观界面,有了这个Facade类,那么客户端就不需要亲自调用子系统中的A、B、C模块了,也不需要知道系统内部的实现细节,甚至都不需要知道A、B、C模块的存在,客户端只需要跟Facade类交互就好了,从而更好地实现了客户端和子系统中A、B、C模块的解耦,让客户端更容易地使用系统。
门面模式的实现
使用门面模式还有一个附带的好处,就是能够有选择性地暴露方法。一个模块中定义的方法可以分成两部分,一部分是给子系统外部使用的,一部分是子系统内部模块之间相互调用时使用的。有了Facade类,那么用于子系统内部模块之间相互调用的方法就不用暴露给子系统外部了。
比如,定义如下A、B、C模块。
public class Module {
/**
* 提供给子系统外部使用的方法
*/
public void a1(){}; /**
* 子系统内部模块之间相互调用时使用的方法
*/
public void a2(){};
public void a3(){};
}
public class ModuleB {
/**
* 提供给子系统外部使用的方法
*/
public void b1(){}; /**
* 子系统内部模块之间相互调用时使用的方法
*/
public void b2(){};
public void b3(){};
}
public class ModuleC {
/**
* 提供给子系统外部使用的方法
*/
public void c1(){}; /**
* 子系统内部模块之间相互调用时使用的方法
*/
public void c2(){};
public void c3(){};
}
public class ModuleFacade { ModuleA a = new ModuleA();
ModuleB b = new ModuleB();
ModuleC c = new ModuleC();
/**
* 下面这些是A、B、C模块对子系统外部提供的方法
*/
public void a1(){
a.a1();
}
public void b1(){
b.b1();
}
public void c1(){
c.c1();
}
}
这样定义一个ModuleFacade类可以有效地屏蔽内部的细节,免得客户端去调用Module类时,发现一些不需要它知道的方法。比如a2()和a3()方法就不需要让客户端知道,否则既暴露了内部的细节,又让客户端迷惑。对客户端来说,他可能还要去思考a2()、a3()方法用来干什么呢?其实a2()和a3()方法是内部模块之间交互的,原本就不是对子系统外部的,所以干脆就不要让客户端知道。
一个系统可以有几个门面类
在门面模式中,通常只需要一个门面类,并且此门面类只有一个实例,换言之它是一个单例类。当然这并不意味着在整个系统里只有一个门面类,而仅仅是说对每一个子系统只有一个门面类。或者说,如果一个系统有好几个子系统的话,每一个子系统都有一个门面类,整个系统可以有数个门面类。
为子系统增加新行为
初学者往往以为通过继承一个门面类便可在子系统中加入新的行为,这是错误的。门面模式的用意是为子系统提供一个集中化和简化的沟通管道,而不能向子系统加入新的行为。比如医院中的接待员并不是医护人员,接待员并不能为病人提供医疗服务。
门面模式的优点
门面模式的优点:
● 松散耦合
门面模式松散了客户端与子系统的耦合关系,让子系统内部的模块能更容易扩展和维护。
● 简单易用
门面模式让子系统更加易用,客户端不再需要了解子系统内部的实现,也不需要跟众多子系统内部的模块进行交互,只需要跟门面类交互就可以了。
● 更好的划分访问层次
通过合理使用Facade,可以帮助我们更好地划分访问的层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到门面中,这样既方便客户端使用,也很好地隐藏了内部的细节。
门面模式在Tomcat中的使用
Tomcat中门面模式使用的很多,因为Tomcat中有很多不同组件,每个组件要相互通信,但是又不能将自己内部数据过多的暴露给其他组件。用门面模式隔离数据是个很好的方法。
下面是Request上使用的门面模式:
使用过Servlet的人都清楚,除了要在web.xml做相应的配置外,还需继承一个叫HttpServlet的抽象类,并且重写doGet与doPost方法(当然只重写service方法也是可以的)。
public class TestServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { } }
可以看出doGet与doPost方法有两个参数,参数类型是接口HttpServletRequest与接口HttpServletResponse,那么从Tomcat中传递过来的真实类型到底是什么呢?通过debug会发现,在真正调用TestServlet类之前,会经过很多Tomcat中的方法。如下图所示
aaarticlea/png;base64,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" alt="" />
注意红色方框圈中的类,StandardWrapperValue类中的invoke方法225行代码如下:
filterChain.doFilter
(request.getRequest(), response.getResponse());
在StandardWrapperValue类中并没有直接将Request对象与Response对象传递给ApplicationFilterChain类的doFilter方法,传递的是RequestFacade与ResponseFacade对象,为什么这么说呢,看一下request.getRequest()与response.getResponse()方法就真相大白了。
Request类
public HttpServletRequest getRequest() {
if (facade == null) {
facade = new RequestFacade(this);
}
return facade;
}
Response类
public HttpServletResponse getResponse() {
if (facade == null) {
facade = new ResponseFacade(this);
}
return (facade);
}
可以看到它们返回都是各自的一个门面类,那么这样做有什么好处呢?
Request对象中的很多方法都是内部组件之间相互交互时使用的,比如setComet、setRequestedSessionId等方法(这里就不一一列举了)。这些方法并不对外部公开,但是又必须设置为public,因为还需要跟内部组件之间交互使用。最好的解决方法就是通过使用一个Facade类,将与内部组件之间交互使用的方法屏蔽掉,只提供给外部程序感兴趣的方法。
如果不使用Facade类,直接传递的是Request对象和Response对象,那么熟悉容器内部运作的程序员可以分别把ServletRequest和ServletResponse对象向下转换为Request和Response,并调用它们的公共方法。比如拥有Request对象,就可以调用setComet、setRequestedSessionId等方法,这会危害安全性。
原文地址:《JAVA与模式》之门面模式
《JAVA设计模式》之外观模式(Facade)的更多相关文章
- 乐在其中设计模式(C#) - 外观模式(Facade Pattern)
原文:乐在其中设计模式(C#) - 外观模式(Facade Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 外观模式(Facade Pattern) 作者:webabcd 介绍 ...
- 8.4 GOF设计模式三: 外观模式 Facade
GOF设计模式三: 外观模式 Facade “现有系统”功能强大.复杂,开发“新系统”需要用到其中一部分,但又要增加一部 分新功能,该怎么办?4.1 Facade Pattern: Key Fea ...
- 二十四种设计模式:外观模式(Facade Pattern)
外观模式(Facade Pattern) 介绍为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用.示例有一个Message实体类,某对象对它 ...
- 【JAVA设计模式】外观模式(Facade Pattern)
一 定义 为子系统中的一组接口提供一个一致的界面.Facade模式定义了一个高层的接口,这个接口使得这一子系统更加easy使用. 二 案例 一个子系统中拥有3个模块.每一个模块中都有3个方法.当中 ...
- java设计模式之外观模式(门面模式)
针对外观模式,在项目开发和实际运用中十分频繁,但是其极易理解,下面就简要介绍一下. 一.概念介绍 外观模式(Facade),他隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口.这种类型的设计 ...
- [设计模式] 10 外观模式 facade
外观模式应该是用的很多的一种模式,特别是当一个系统很复杂时,系统提供给客户的是一个简单的对外接口,而把里面复杂的结构都封装了起来.客户只需使用这些简单接口就能使用这个系统,而不需要关注内部复杂的结构. ...
- 设计模式 笔记 外观模式 Facade
//---------------------------15/04/16---------------------------- //Facade 外观模式-----对象结构型模式 /* 1:意图: ...
- 设计模式之外观模式(Facade)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- Java设计模式之五 ----- 外观模式和装饰器模式
前言 在上一篇中我们学习了结构型模式的适配器模式和桥接模式.本篇则来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这 ...
- 【设计模式】—— 外观模式Facade
前言:[模式总览]——————————by xingoo 模式意图 外观模式主要是为了为一组接口提供一个一致的界面.从而使得复杂的子系统与用户端分离解耦. 有点类似家庭常用的一键开关,只要按一个键,台 ...
随机推荐
- Failed to determine the https port for redirect
原文:Failed to determine the https port for redirect warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedir ...
- 修改url,
第一种场景: 无论url怎么变,表单里面的url始终不变 http://127.0.0.1:8000/CC/indexssssssssssssssssss/ url(r'^indexsssssssss ...
- VirtualBox中安装CentOS 7
1.如下所示图,点击“新建”,创建一个新的虚拟机 2.类型选择Linux,版本选择Red Hat,下一步 3.分配内存大小,电脑8G内存,所以分给虚拟机2G,选择下一步 4.选择“现在创建虚拟硬盘” ...
- Mysql 数据库中9大对象
MySql 数据库9中对象1.表2.索引3.视图4.图表:数据库表之间的关系视图,并不常用5.规则6.缺省值:数据列的默认值7.触发器8.存储过程9.用户
- LNMP集群架构篇
一.LNMP介绍 1.使前端web服务和后端存储服务进行串联 2.主要实现处理php动态请求 工作原理: L:linux N:nginx M:mysql P:php 二.lnmp部署 我的环境 ...
- head 显示文件头部内容
1. 命令功能 head 默认显示文件前10行内容. 2.语法格式 head option file 参数说明 参数 参数说明 -n 指定显示行数 -c 指定显示的字节数 -v 总是显示文件名的文件头 ...
- 安装Git,Maven,配置ssh认证
安装git: yum -y install git 安装maven: wget http://mirror.bit.edu.cn/apache/maven/maven-3/3.6.1/binaries ...
- Flutter-網絡請求
Flutter 请求网络的三种方式 flutter 请求网络的方式有三种,分别是 Dart 原生的网络请求 HttpClient.第三方网络请求 http以及 Flutter 中的 Dio.我们可以比 ...
- Java类加载器初识
类加载器基本概念 类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.一般来说,Java虚拟机使用Java类的方式如下:Java 源程序(.java 文件)在经过 Jav ...
- Linux g++ 编译添加 pthread
If you are going to compile a C program with pthread.h in LINUX using GCC or G++ you will have to us ...