Facade模式

    又称外观模式。这个模式是现实中很常见到的一种模式,比如汽车的设计,汽车里面是很复杂的,但是开汽车是很简单的,为什么?因为汽车设计人员把汽车的复杂部分“封装”在汽车里面,只提供很简单易用的方向盘、刹车和加油给你控制汽车。这就是Facade模式,我们需要一个更简单的方式使用一个复杂的东西,并可满足我们的需要。
  通常我们的一个应用系统会划分成几个子系统,实际的一个应用中可能对应不同的子系统。外部接口与内部子系统之间的交互使用Facade来实现,让两者没有耦合关系。如果客户程序与组件中各种子系统有很过多的耦合,随着外部客户程序和各子系统的演化,这种耦合就会面临很多变化的挑战。一个汽车引擎的更改就要修改所有的引用它的部分。简化外部程序和系统之间的交互接口,使用Facade将外部客户程序的演化和内部子系统的变化之间的依赖相互解耦。

  
名称 Facade
结构 我的设计模式学习--Facade(外观模式)
意图 为子系统中的一组接口提供一个一致的界面,F a c a d e 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
适用性
  • 当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。F a c a d e 可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过f a c a d e 层。
  • 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入f a c a d e 将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
  • 当你需要构建一个层次结构的子系统时,使用f a c a d e 模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过f a c a d e 进行通讯,从而简化了它们之间的依赖关系。
Code Example
 1我的设计模式学习--Facade(外观模式)// Facade
 2我的设计模式学习--Facade(外观模式)
 3我的设计模式学习--Facade(外观模式)// Intent: "Provide a unified interface to a set of interfaces in a subsystem.
 4我的设计模式学习--Facade(外观模式)// Facade defines a higher-level interface that makes the subsystem easier
 5我的设计模式学习--Facade(外观模式)// to use". 
 6我的设计模式学习--Facade(外观模式)
 7我的设计模式学习--Facade(外观模式)// For further information, read "Design Patterns", p185, Gamma et al.,
 8我的设计模式学习--Facade(外观模式)// Addison-Wesley, ISBN:0-201-63361-2
 9我的设计模式学习--Facade(外观模式)
10

我的设计模式学习--Facade(外观模式)

 
设计

那么如何能简单的使用一个复杂的东西呢?只需要这个复杂的东西提供我所需的功能就行了。比如,汽车向前行驶对汽车本身是一个很复杂的系统,要抽汽油燃烧,通过引擎形成动力,再通过承轴传到轮胎上,使轮胎滚动,从而使汽车前进。如果我们开车需要去控制汽车内部的这些部件的运转的话,估计没人能学会开车。那么怎么办?很简单,汽车提供一个功能——加油,我们只要脚踏油门,汽车就会前进。这样,大家都能很容易学会开车了。

 

我的设计模式学习--Facade(外观模式)
3.3     
实现

UML图:

示例代码为:

 1我的设计模式学习--Facade(外观模式)using System;
 2我的设计模式学习--Facade(外观模式)
 3我的设计模式学习--Facade(外观模式)namespace Example
 4
====================================================================================

一、 门面(Facade)模式

外部与一个子系统的通信必须通过一个统一的门面(Facade)对象进行,这就是门面模式。

医院的例子

用一个例子进行说明,如果把医院作为一个子系统,按照部门职能,这个系统可以划分为挂号、门诊、划价、化验、收费、取药等。看病的病人要与这些部门打交道,就如同一个子系统的客户端与一个子系统的各个类打交道一样,不是一件容易的事情。

首先病人必须先挂号,然后门诊。如果医生要求化验,病人必须首先划价,然后缴款,才能到化验部门做化验。化验后,再回到门诊室。

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

什么是门面模式

门面模式要求一个子系统的外部与其内部的通信必须通过一个统一的门面(Facade)对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。

就如同医院的接待员一样,门面模式的门面类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与门面对象打交道,而不需要与子系统内部的很多对象打交道。


二、 门面模式的结构

门面模式是对象的结构模式。门面模式没有一个一般化的类图描述,下图演示了一个门面模式的示意性对象图:

 我的设计模式学习--Facade(外观模式)

在这个对象图中,出现了两个角色:

门面(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。

子系统(subsystem)角色:可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。


三、 门面模式的实现

一个系统可以有几个门面类

【GOF】的书中指出:在门面模式中,通常只需要一个门面类,并且此门面类只有一个实例,换言之它是一个单例类。当然这并不意味着在整个系统里只能有一个门面类,而仅仅是说对每一个子系统只有一个门面类。或者说,如果一个系统有好几个子系统的话,每一个子系统有一个门面类,整个系统可以有数个门面类。

为子系统增加新行为

初学者往往以为通过继承一个门面类便可在子系统中加入新的行为,这是错误的。门面模式的用意是为子系统提供一个集中化和简化的沟通管道,而不能向子系统加入新的行为。


四、 在什么情况下使用门面模式

  • 为一个复杂子系统提供一个简单接口
  • 提高子系统的独立性
  • 在层次化结构中,可以使用Facade模式定义系统中每一层的入口。


五、 一个例子

我们考察一个保安系统的例子,以说明门面模式的功效。一个保安系统由两个录像机、三个电灯、一个遥感器和一个警报器组成。保安系统的操作人员需要经常将这些仪器启动和关闭。

不使用门面模式的设计

首先,在不使用门面模式的情况下,操作这个保安系统的操作员必须直接操作所有的这些部件。下图所示就是在不使用门面模式的情况下系统的设计图。

 我的设计模式学习--Facade(外观模式)


可以看出,Client对象需要引用到所有的录像机(Camera)、电灯(Light)、感应器(Sensor)和警报器(Alarm)对象。代码如下:

我的设计模式学习--Facade(外观模式)using System;
我的设计模式学习--Facade(外观模式)
我的设计模式学习--Facade(外观模式)
public class Camera
}

 

六、 使用门面模式的设计

一个合情合理的改进方法就是准备一个系统的控制台,作为保安系统的用户界面。如下图所示:

 我的设计模式学习--Facade(外观模式)

程序代码如下:

我的设计模式学习--Facade(外观模式)using System;
我的设计模式学习--Facade(外观模式)
我的设计模式学习--Facade(外观模式)
public class Camera
}

 

相关文章:

  • 2021-06-16
  • 2021-12-07
  • 2022-01-22
  • 2021-09-28
  • 2022-01-15
猜你喜欢
  • 2022-12-23
  • 2021-06-29
  • 2021-08-12
  • 2022-01-08
  • 2022-01-08
  • 2022-01-08
  • 2022-01-08
相关资源
相似解决方案