看到“门面”这个词,大家一定都觉得很熟悉。不错,这个词正是借用了我们日常生活中的“门面”的概念。日常生活中的“门面”,正是我们买东西的地方。因此可以这么说,“门面”就是这么一个地方,它们跟各种商品的生产商打交道,收集商品后,再卖给我们。换句话说,如果没有“门面”,我们将不得不直接跟各种各样的生产商买商品;而有了“门面”,我们要买东西,直接跟“门面”打交道就可以了。

Facade模式正是这样一个“门面”:我们本来需要与后台的多个类或者接口打交道,而Facade模式是客户端和后台之间插入一个中间层——门面,这个门面跟后台的多个类或接口打交道,而客户端只需要跟门面打交道即可。

使用Facade模式可以说是后台设计和编码人员的一个必备素质。我不止碰到过一个这样的后台开发人员,他们认为只要把后台功能完成了就万事大吉,而没有站在后台使用者的角度来看一看自己写出来的代码。其实,我们写出来的后台代码是要给别人使用的,所以我们提供给使用者的接口要越简单越好,这不单是对使用者好,同时对开发者也是好处多多的,至少你的接口简单了,你和使用者的交流就容易了。

而Facade模式中的Facade类正是这样一个用户接口,它和后台中的多个类产生依赖关系,而后台的客户类则只跟Facade类产生依赖关系。为什么要这么做?其中的原因十分简单:后台的开发者熟悉他自己开发的各个类,也就容易解决和多个类的依赖关系,而后台的使用者则不太熟悉后台的各个类,不容易处理和它们之间的依赖;因此,后台的开发者自己在Facade类中解决了与后台多个类之间的依赖,后台的使用者只需要处理和Facade类的依赖即可。

好了,闲话少说。我们下面就以几个具体的例子来看一看Facade模式是怎么使用的。实际编程中,能使用到Facade模式的情况有很多,以下就分两种情况来具体说一说Facade模式的使用。可能还会有其他的情况,大家在实践中也可以加以补充。

第一种情况,客户类要使用的功能分布在多个类中,这些类可能相互之间没有什么关系;客户在使用后台的时候,必须先初始化要使用到的功能所在的类,然后才能使用。这时候,适合将这些功能集中在一个Facade类里,还可以替用户做一些初始化的工作,以减轻用户的负担。
例如,以商店为例。假如商店里出售三种商品:衣服、电脑和手机。这三种商品都是由各自的生产厂商卖出的,如下:
public class CoatFactory
{
public Coat saleCoat()
{
……
return coat;
}
……
}

然后是电脑的厂家类:

public class ComputerFactory
{
public Computer saleComputer()
{
……
return computer;
}
……
}

最后是手机商类:

public class MobileFactory
{
public Mobile saleMobile()
{
……
return mobile;
}
……
}

如果没有商店,我们就不得不分别跟各自的生产商打交道,如下:

//买衣服
CoatFactory coatFactory = new CoatFactory();
coatFactory.saleCoat();
//买电脑
ComputerFactory computerFactory = new ComputerFactory();
computerFactory.saleComputer();
//买手机
MobileFactory mobileFactory = new MobileFactory();
mobileFactory.saleMobile();

对我们顾客来说,和这么多的厂家类打交道,这显然是够麻烦的。

这样,我们就需要创建一个商店类了,让商店类和这些厂家打交道,我们只和商店类打交道即可,如下:

public class Store
{
public Coat saleCoat()
{
CoatFactory coatFactory = new CoatFactory();
return coatFactory.saleCoat();
}
public Computer saleComputer()
{
ComputerFactory computerFactory = new ComputerFactory();
return computerFactory.saleComputer();
}
public Mobile saleMobile()
{
MobileFactory mobileFactory = new MobileFactory();
return mobileFactory.saleMobile();
}
}

好了,现在我们要买东西,不用去跟那么多的厂家类打交道了。

Store store =new Store();
//买衣服
store.saleCoat();
//买电脑
store.saleComputer();
//买手机
store.saleMobile();

呵呵,这样对我们客户类来说,是不是简单多了。

第二种情况客户要完成的某个功能,可能需要调用后台的多个类才能实现,这时候特别要使用Facade模式。不然,会给客户的调用带来很大的麻烦。请看下面的例子。

我经常看到后台编码人员,强迫它们的使用者写出如下的代码:

……
String xmlString = null;
int result = 0;
try
{
xmlString = gdSizeChart.buildDataXML(incBean);

String path = "D:/Eclipse3.0/workspace/PLMSuite/AppWeb/PM/productSpecification/gridfile.xml";
File f = new File(path);
PrintWriter out = new PrintWriter(new FileWriter(f));
out.print(xmlString);
out.close();
System.out.println("/r/n/r/n sumaryAction" + xmlString + "/r/n/r/n");
request.setAttribute("xmlString", xmlString);
}
catch(Exception ex)
{
ex.printStackTrace();
}

这段代码前面即省略号省略掉的一部分是客户类调用后台的一部分代码,是一个相对独立的功能。后面这一部分也是一个相对独立的功能,而后台代码设计人员却把这个功能留给客户类自己来实现。

我就很怀疑,让客户类做这么多事情,到底要你的后台做什么?你还不如直接把所有的事情都给客户类做了得了。因为,你后台做了一半,剩下的一部分给客户类做,客户类根本就不明白怎么回事,或者说他不清楚你的思路,这样做下去更加困难。可能这点逻辑对你来说,很简单。但使用者不明白你的思路啊,他不知道来龙去脉,怎么往下写?

如果在这里有一个Facade类,让它来做不该由客户类来做的事,是不是简单多了呢?如下是一个Facade类:

public class Facade
{
public static void doAll(PE_MeasTableExdBean incBean, HttpServletRequest request)
{
……
request.setAttribute(“xmlString”,Facade.getFromOut(incBean));
}
private static String getFromOut(PE_MeasTableExdBean incBean)
{
try
{
xmlString = gdSizeChart.buildDataXML(incBean);

String path = "D:/Eclipse3.0/workspace/PLMSuite/AppWeb/PM/productSpecification/gridfile.xml";
File f = new File(path);
PrintWriter out = new PrintWriter(new FileWriter(f));
out.print(xmlString);
out.close();
System.out.println("/r/n/r/n sumaryAction" + xmlString + "/r/n/r/n");
return xmlString;
}
catch(Exception ex)
{
ex.printStackTrace();
return null;
}
}
}

那么客户类的调用就是下面的样子:

Facade.doAll(incBean,request);

这样,客户是不是轻松多了?值得注意的是,Facade类中的getFromOut方法其实不应该在Facade类中,本文为了简单起见而放在了这个类中,对Facade类来说是不符合单一职责原则的。

最后总结一下第二种情况的模式。后台为实现某一个功能有如下类:

public class ClassA
{
public void doA()
{
……
}
……
}
public class ClassB
{
public void doB()
{
……
}
……
}
public class ClassC
{
public void doC()
{
……
}
……
}

如果客户类需要这样调用:

……
ClassA a = new ClassA();
a.doA();
ClassB b = new ClassB();
b.doB();
ClassC c = new ClassC();
c.doC();
……

那么就适合做一个Facade类,来替客户类来完成上述的功能,如下:

public class Facade
{
public void doAll()
{
ClassA a = new ClassA();
a.doA();
ClassB b = new ClassB();
b.doB();
ClassC c = new ClassC();
c.doC();
}
}

则客户类的调用如下:

……
Facade Facade = new Facade();
Facade.doAll();
……

代码的“门面”——模式系列谈之Facade模式相关推荐

  1. 外观(Facade)模式

    文章目录 外观(Facade)模式 1. 意图 2. 别名 3. 动机 4. 适用性 5. 结构 6. 参与者 7. 协作 8. 效果 9. 实现 10. 代码示例 11. 已知应用 12. 相关模式 ...

  2. 结构型模式之Facade模式

    1.意图 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这个子系统更加容易使用. 2.适用性 以下情况使用Facade模式 (1)当你要为一个复杂子系统提供一 ...

  3. GOF 设计模式Facade模式 笔记

    Facade(外观) 意图:为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 结构图 在以下情况使用: 当你要为一个复杂子系统提供一个简 ...

  4. 设计模式:Facade模式

    Facade模式--简单窗口 当调用大型程序进行处理时,我们需要格外注意那些数量庞大的类之间错综复杂的关系.不过有一种更简单的做法,就是为这个大型程序提供一个"窗口".这样,我们就 ...

  5. Facade模式(门面模式)

    模式简介 门面模式用于客户端与内部系统的解耦,客户端对内部系统的调用封装在门面类中,让客户端通过门面类调用功能,从而简化了客户端对内部系统的调用. 模式UML图 代码示例(C#) 提示:可在本栏目的资 ...

  6. 设计模式--门面(Facade)模式

    模式定义 为子系统中的一组接口提供一个一致(稳定)的界面,Facade模式定义了一个高层接口,这个接口使得这个子系统更加容易使用(复用) 类图 应用场景 1.当你需要使用复杂子系统的有限但直接的接口时 ...

  7. 门面模式(Facade模式)详解

    在现实生活中,常常存在办事较复杂的例子,如办房产证或注册一家公司,有时要同多个部门联系,这时要是有一个综合部门能解决一切手续问题就好了. 软件设计也是这样,当一个系统的功能越来越强,子系统会越来越多, ...

  8. 6中结构型设计模式的对比理解(Composite组合模式,Proxy代理模式,Flyweight享元模式,Facade门面模式,Bridge桥接模式,Decorator装饰器模式)

    结构型模式 结构型模式用来组装 类和对象,以获得更大的结构. 结构型类模式,通过继承机制来组合接口或类.简单的例子就是多重继承,最后一个类拥有所有父类的性质.这个模式有助于独立开发一个协同类.另一个例 ...

  9. 门面模式、调停者模式、责任链模式

    简介: 1.门面模式(facade) 门面模式:比如政府部门,你需要提交一些资料证明你自己是你自己,可能会从这个部门跑到那个部门,串来串去都办不好,但是如果有一个部门来统一协调这些部门之间的关系,而你 ...

最新文章

  1. webstorm打包rn项目_React 之 项目搭建
  2. Java定义接口变量为接收类型有什么好处(面向接口编程)
  3. python的mysql模块_python使用MySQLdb模块连接MySQL
  4. DCMTK:测试DcmSCP和DcmSCU类
  5. 腾讯陈妍:万物互联时代,保险业应更注重服务创新来挖掘用户需求
  6. jMeter 里如何调用函数 function
  7. python200行代码_如何用200行Python代码“换脸”
  8. 为什么说下一个十年的主战场在Serverless?
  9. android 抓取webview中的所有图片_如何一键提取PDF文档中的所有图片?
  10. 软件外包项目实施过程中的关键因素(摘自IT168技术频道)
  11. [转]jQuery为控件添加水印文字
  12. 云鲸扫拖一体机器人说明书_云鲸小白鲸扫拖一体机器人好用吗?真实的测评带你走进智能化家居时代...
  13. DBeaver mysql驱动连接问题
  14. 3D游戏中的数学基础
  15. 市场上最受欢迎的十大服装进销存软件
  16. 淋雨量matlab,最小淋雨量问题
  17. ajax请求是宏任务还是微任务_ASP.NET Web API基础(04)---异步编程和跨域请求 - 高原秃鹫...
  18. 为什么很多人工作都不开心
  19. blender合并物体后材质丢失问题的解决办法
  20. 关于SecureCRT工具的使用

热门文章

  1. [Java初学]Java上溯造型(upcasting)与下溯造型(Downcasting)
  2. python 升级setuptools_python3.6升级及setuptools、pip安装
  3. 虚拟机显示网络不可用
  4. html中repeat的作用,repeat-y
  5. VPU?APU?GPU?折腾从AMD-GPU回到Intel核显+OpenCL+Linux环境搭建
  6. 李永乐(七)向量组的秩、矩阵的秩——笔记
  7. 1120_野火RT-Thread教程学习4_RTT学习基础知识梳理
  8. 林深时见鹿,海蓝时见鲸
  9. arduino串口绘图_Arduino IDE开发环境串口绘图仪(Serial Plotter)使用方法简介
  10. 《幸运大转盘》代码分享