外观模式

外观模式是对象的结构模式,外部与一个子系统的通信必须通过一个统一的外观对象进行。外观模式是一个高层次的接口,使得子系统更易于使用。

医院的例子

现代的软件系统都是比较复杂的。假如把医院比作一个子系统,按照部门职能,这个系统划分为挂号、门诊、划价、化验、收费、取药等。看病的人要与这些部门打交道,就如同一个子系统的客户端与一个子系统的各个类打交道一样,不是一件容易的事。

解决这种不便的方法便是引入外观模式,医院可以设置一个接待员的位置,由接待员负责代为挂号、划价、缴费、取药等。病人只需要接触接待员,由接待员与各个部门打交道。

外观模式的结构

外观模式的结构可以这么表示:

这个图中,体现了两种角色:

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中,这样既方便客户端使用,也很好地隐藏了内部的细节

Java设计模式11:外观模式的更多相关文章

  1. C#设计模式(11)——外观模式(Facade Pattern)

    一.引言 在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然而为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ...

  2. 【JAVA设计模式】外观模式(Facade Pattern)

    一  定义 为子系统中的一组接口提供一个一致的界面.Facade模式定义了一个高层的接口,这个接口使得这一子系统更加easy使用. 二  案例 一个子系统中拥有3个模块.每一个模块中都有3个方法.当中 ...

  3. java设计模式之外观模式(门面模式)

    针对外观模式,在项目开发和实际运用中十分频繁,但是其极易理解,下面就简要介绍一下. 一.概念介绍 外观模式(Facade),他隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口.这种类型的设计 ...

  4. 再起航,我的学习笔记之JavaScript设计模式11(外观模式)

    经过一段时间的学习与分享,我们对创建型设计模式已经有了一定的认识,未来的一段时间里我们将展开新的篇章,开始迈入结构性设计模式的学习. 结构性设计模式与创建型设计模式不同,结构性设计模式更偏向于关注如何 ...

  5. C#设计模式(11)——外观模式(Facade Pattern)(转)

    一.引言 在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然而为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ...

  6. Java设计模式之五 ----- 外观模式和装饰器模式

    前言 在上一篇中我们学习了结构型模式的适配器模式和桥接模式.本篇则来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这 ...

  7. C#设计模式(11)——外观模式

    一.概念 外观模式提供了一个统一的接口,用来访问子系统中的一群接口.外观定义了一个高层接口,让子系统更容易使用.使用外观模式时,我们创建了一个统一的类,用来包装子系统中一个或多个复杂的类,客户端可以直 ...

  8. Java设计模式之外观模式和最少知识原则

    外观模式: 外观模式:提供一个统一的接口,来访问子系统中一群功能相关接口(类似一键启动,一键关闭等等) 外观模式定义了一个高层接口,让子系统更容易使用 降低对外接口耦合度 外观模式和命令模式各自侧重点 ...

  9. java设计模式之外观模式

    外观模式概念 外观模式又称为门面模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个搞层次接口,使得这一个子系统更加容易使用.这一模式完美的体现了依赖倒转原则和迪米特法则的思想,所以是非常常 ...

  10. 由一名保安引发的Java设计模式:外观模式

    目录 应用场景 外观模式 定义 意图 主要解决问题 何时使用 优缺点 结构 保安的故事 应用场景 使用方要完成一个功能,需要调用提供方的多个接口.方法,调用过程复杂时,我们可以再提供一个高层接口(新的 ...

随机推荐

  1. DIV+CSS常用的网页布局代码

    单行一列以下是引用片段:body { margin: 0px; padding: 0px; text-align: center; }#content { margin-left:auto; marg ...

  2. 理解soft-clipped reads

    什么是soft-clipped reads 当基因组发生某一段的缺失,或转录组的剪接,在测序过程中,横跨缺失位点及剪接位点的reads回帖到基因组时,一条reads被切成两段,匹配到不同的区域,这样的 ...

  3. vs2015 command prompt here

    网上搜的很多方法都不能用,比如:http://app.paraesthesia.com/CommandPromptHere/ 主要是都搞错了注册表路径,写成了: HKCR,Directory\Shel ...

  4. python第二天基础1-1

    一.作用域 对于变量的作用域,执行声明并在内存中存在,该变量就可以在下面的代码中使用. if 1==1: name = 'wupeiqi' print name 二.三元运算 result = 值1  ...

  5. 关于swfupload,客户端中文乱码解决方案!

    公司做了个邮箱系统,上传附件用到了swfupload控件,测试成功上线后hr找我说上传附件中文乱码. 奇怪了,就只有她的电脑出问题,我找了好几台电脑,虚拟机也跑了怎么就找不到问题. 后来网上查了好久, ...

  6. 给自己立下一个巨大的flag

    [BZOJ1861][BZOJ3224] [BZOJ2733][BZOJ1056] [BZOJ2120][BZOJ3673] [BZOJ1833][BZOJ1026] [BZOJ3209][BZOJ1 ...

  7. 浅入了解GCD 并发 并行 同步 异步 多线程

     什么是 GCD?! GCD就是一个函数库(废话) 用来压榨系统的资源,解决多线程处理中一些问题的库(知道这个就够了,很多电影角色都是因为知道太多死得很惨!!!!!) 1.并发与并行 Concurre ...

  8. JavaScript-永远点不到的小窗口

    <!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. How to Use Lucene.NET with Windows Azure SQL Database

    http://social.technet.microsoft.com/wiki/contents/articles/2367.how-to-use-lucene-net-with-windows-a ...

  10. 浅谈城市规划在移动GIS方面的应用发展

    1.概述 城市建设进程加快,城市规划管理工作日趋繁重,各种来源的数据产生各种层出不穷的问题,严重影响城市规划时的准确性,为此全面合理的掌握好各方面的城市规划资料才能做出更加科学的决策.移动端的兴起为规 ...