JAVA设计模式之门面模式
在阎宏博士的《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设计模式之门面模式以及在java中作用
门面模式在Tomcat中有多处使用,在Request和Response对象封装,从ApplicationContext到ServletContext封装中都用到了这种设计模式. 一个系统可以有几个门面 ...
- JAVA设计模式之门面模式(外观模式)
医院的例子 现代的软件系统都是比较复杂的,设计师处理复杂系统的一个常见方法便是将其“分而治之”,把一个系统划分为几个较小的子系统.如果把医院作为一个子系统,按照部门职能,这个系统可以划分为挂号.门诊. ...
- Java设计模式——装饰者模式
JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...
- 浅析JAVA设计模式之工厂模式(一)
1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...
- JAVA设计模式--装饰器模式
装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...
- 折腾Java设计模式之建造者模式
博文原址:折腾Java设计模式之建造者模式 建造者模式 Separate the construction of a complex object from its representation, a ...
- 折腾Java设计模式之备忘录模式
原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...
- 折腾Java设计模式之状态模式
原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...
- 折腾Java设计模式之模板方法模式
博客原文地址:折腾Java设计模式之模板方法模式 模板方法模式 Define the skeleton of an algorithm in an operation, deferring some ...
随机推荐
- CentOS6.4安装Hadoop2.0.5 alpha - 3-Node Cluster
1.在第2个个节点上重复http://www.cnblogs.com/littlesuccess/p/3361497.html文章中的第1-5步 2.修改第1个节点上的hdfs-site.xml中的配 ...
- HDU1004 BALLO0N
Let the Balloon Rise Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- megapix-image插件 使用Canvas压缩图片上传 解决手机端图片上传功能的问题
最近在弄微信端的公众号.订阅号的相关功能,发现原本网页上用的uploadify图片上传功能到手机端有的手机类型上就不能用了,比如iphone,至于为啥我想应该不用多说了吧(uploadify使用fla ...
- checkbox选中与取消选择
先上代码 <form> 你爱好的运动是?<br/> <input type="checkbox" name="items" val ...
- Python学习路程day13
JavaScript JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. ...
- SQLAlchemy一对多总结
1.SQLAlchemy之一对多关系 1.1 创建单表 class Test(Base): __tablename__ = 'user' nid = Colume(Integer,primary_ke ...
- UE4 Tutorial - Custom Mesh Component 用于绘制自定义网格的插件CustomMeshComponent
UE4 中用于绘制自定义网格的插件CustomMeshComponent. 转载: UE4 Tutorial - Custom Mesh Component Over the last few w ...
- Bower安装Bootstrap
1.Bower简介 官网:https://bower.io/ Bower can manage components that contain HTML, CSS, JavaScript, fonts ...
- 三部曲二(基本算法、动态规划、搜索)-1003-Lucky and Good Months by Gregorian Calendar
模拟加阅读题......虽然很多事常识性的知识,但也有许多不知道的知识,关键是不读不知道那些是已经知道的那些不是,许多重要的信息零散的分布在一大坨英文里,读起来很痛苦......自己读了一遍,读的晕晕 ...
- iOS 利用 Framework 进行动态更新
http://nixwang.com/2015/11/09/ios-dynamic-update/ 前言 目前 iOS 上的动态更新方案主要有以下 4 种: HTML 5 lua(wax)hotpat ...