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

医院的例子

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

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

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

什么是门面模式

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

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

二、 门面模式的结构

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

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

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

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

三、 门面模式的实现

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

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

为子系统增加新行为

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

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

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

五、 一个例子

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

不使用门面模式的设计

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

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

using System;

public class Camera
{
  public void TurnOn()
  {
    Console.WriteLine("Turning on the camera.");
  }

  public void TurnOff()
  {
    Console.WriteLine("Turning off the camera.");
  }

  public void Rotate(int degrees)
  {
    Console.WriteLine("Rotating the camera by {0} degrees.", degrees);
  }
}

public class Light
{

  public void TurnOff()
  {
    Console.WriteLine("Turning on the light.");
  }

  public void TurnOn()
  {
    Console.WriteLine("Turning off the light.");
  }

  public void ChangeBulb()
  {
    Console.WriteLine("changing the light-bulb.");
  }
}

public class Sensor
{
  public void Activate()
  {
    Console.WriteLine("Activating the sensor.");
  }

  public void Deactivate()
  {
    Console.WriteLine("Deactivating the sensor.");
  }

  public void Trigger()
  {
    Console.WriteLine("The sensor has triggered.");
  }
}

public class Alarm
{

  public void Activate()
  {
    Console.WriteLine("Activating the alarm.");
  }

  public void Deactivate()
  {
    Console.WriteLine("Deactivating the alarm.");
  }

  public void Ring()
  {
    Console.WriteLine("Ringing the alarm.");
  }

  public void StopRing()
  {
    Console.WriteLine("Stop the alarm.");
  }
}

public class Client
{
  private static Camera camera1, camera2;
  private static Light light1, light2, light3;
  private static Sensor sensor;
  private static Alarm alarm;

  static Client()
  {
    camera1 = new Camera();
    camera2 = new Camera();
    light1 = new Light();
    light2 = new Light();
    light3 = new Light();
    sensor = new Sensor();
    alarm = new Alarm();
  }  

  public static void Main( string[] args )
  {
    camera1.TurnOn();
    camera2.TurnOn();
    light1.TurnOn();
    light2.TurnOn();
    light3.TurnOn();
    sensor.Activate();
    alarm.Activate();
  }
}

六、 使用门面模式的设计

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

程序代码如下:

using System;

public class Camera
{
  public void TurnOn()
  {
    Console.WriteLine("Turning on the camera.");
  }

  public void TurnOff()
  {
    Console.WriteLine("Turning off the camera.");
  }

  public void Rotate(int degrees)
  {
    Console.WriteLine("Rotating the camera by {0} degrees.", degrees);
  }
}

public class Light
{

  public void TurnOff()
  {
    Console.WriteLine("Turning on the light.");
  }

  public void TurnOn()
  {
    Console.WriteLine("Turning off the light.");
  }

  public void ChangeBulb()
  {
    Console.WriteLine("changing the light-bulb.");
  }
}

public class Sensor
{
  public void Activate()
  {
    Console.WriteLine("Activating the sensor.");
  }

  public void Deactivate()
  {
    Console.WriteLine("Deactivating the sensor.");
  }

  public void Trigger()
  {
    Console.WriteLine("The sensor has triggered.");
  }
}

public class Alarm
{

  public void Activate()
  {
    Console.WriteLine("Activating the alarm.");
  }

  public void Deactivate()
  {
    Console.WriteLine("Deactivating the alarm.");
  }

  public void Ring()
  {
    Console.WriteLine("Ringing the alarm.");
  }

  public void StopRing()
  {
    Console.WriteLine("Stop the alarm.");
  }
}

public class SecurityFacade
{
  private static Camera camera1, camera2;
  private static Light light1, light2, light3;
  private static Sensor sensor;
  private static Alarm alarm;

  static SecurityFacade()
  {
    camera1 = new Camera();
    camera2 = new Camera();
    light1 = new Light();
    light2 = new Light();
    light3 = new Light();
    sensor = new Sensor();
    alarm = new Alarm();
  }
  
  public void Activate()
  {
    camera1.TurnOn();
    camera2.TurnOn();
    light1.TurnOn();
    light2.TurnOn();
    light3.TurnOn();
    sensor.Activate();
    alarm.Activate();
  }

  public void Deactivate()
  {
    camera1.TurnOff();
    camera2.TurnOff();
    light1.TurnOff();
    light2.TurnOff();
    light3.TurnOff();
    sensor.Deactivate();
    alarm.Deactivate();
  }
}

public class Client
{
  private static SecurityFacade security;

  public static void Main( string[] args )
  {
    security = new SecurityFacade();
    security.Activate();
    Console.WriteLine("\n--------------------\n");
    security.Deactivate();
  }
}

门面(Facade)模式(转)的更多相关文章

  1. 门面(Facade)模式

    门面模式是对象的结构模式,外部与一个子系统的通信必须通过一个统一的门面对象进行.门面模式提供一个高层次的接口,使得子系统更易于使用. 医院的例子 现代的软件系统都是比较复杂的,设计师处理复杂系统的一个 ...

  2. 十一、外观(Facade)模式--结构模式(Structural Pattern)

    外部与一个子系统的通信必须通过一个统一的门面(Facade)对象进行,这就是门面模式.门面模式要求一个子系统的外部与其内部的通信必须通过一个统一的门面(Facade)对象进行. 门面模式提供一个高层次 ...

  3. 转:Ogre源码分析之Root类、Facade模式

    Ogre源码分析(一)Root类,Facade模式 Ogre中的Root对象是一个Ogre应用程序的主入口点.因为它是整个Ogre引擎的外观(Façade)类.通过Root对象来开启和停止Ogre是最 ...

  4. PHP重载以及Laravel门面Facade

    目录 重载的概念 魔术方法中的重载 属性重载 方法重载 Laravel中的Facade 扩展 谈谈__invoke Laravel提供了许多易用的Facade,让我们用起来特步顺手,那么这些Facad ...

  5. Laravel开发:Laravel框架门面Facade源码分析

    前言 这篇文章我们开始讲 laravel 框架中的门面 Facade,什么是门面呢?官方文档: Facades(读音:/fəˈsäd/ )为应用程序的服务容器中可用的类提供了一个「静态」接口.Lara ...

  6. Python笔记:设计模式之facade模式

    facade模式,即门面模式,也称外观模式,这个模式的核心思想是使用facade对象为外部客户端提供一个统一的访问一组子系统的接口,即客户端不会直接与各个子系统交互,而是通过facade对象与各个子系 ...

  7. C++设计模式-Facade模式

    Facade模式 作用:为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 动机 将一个系统划分成为若干个子系统有利于降低系统的复杂性.一 ...

  8. 外观模式/facade模式/结构型模式

    外观模式 为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式三要素(client-facade-subSystem) 外观角色 ...

  9. 设计模式--外观(Facade)模式

    Insus.NET在去年有写过一篇<软件研发公司,外观设计模式(Facade)>http://www.cnblogs.com/insus/archive/2013/02/27/293606 ...

  10. Facade模式

    Facade模式要求一个子系统的外部与其内部的通信必须通过一个统一的Facade对象进行.Facade模式提供一个高层次的接口,使得子系统更易于使用.  就如同医院的接待员一样,Facade模式的Fa ...

随机推荐

  1. Delphi XE5教程5:程序的结构和语法

    内容源自Delphi XE5 UPDATE 2官方帮助<Delphi Reference>,本人水平有限,欢迎各位高人修正相关错误! 也欢迎各位加入到Delphi学习资料汉化中来,有兴趣者 ...

  2. 1. opencv的初体验

    http://guoming.me/opencv-config  这篇文章有讲解opencv的安装与配置 一些常用库 opencv_core249d.lib opencv_imgproc249d.li ...

  3. DATE,DATETIME,DATETIME2等日期时间数据类型

    日期范围广 0001-01-01 到 9999-12-31.时间范围广 00:00:00 到 23:59:59.9999999. -----------------DATE --只存储日期 selec ...

  4. HTTP 错误405.0 - Method Not Allowed

    在使用IIS发布网页的时候,出现下图这个问题 那么出现这个问题的原因可能有很多种,但是我目前是这么解决的,下面说一下我个人解决这个问题的方案,仅供参考. 首先,以管理员的身份启动cmd 如果电脑是64 ...

  5. MySQL批量杀进程

    OS: CentOS 6.3 DB:5.5.14 mysql> show processlist;+----+------+-----------+--------------------+-- ...

  6. python之量的概念

    程序设计语言: 量的类型: 1. 直接量 2. 常量 3. 变量 量的因素: 1. 存储类别 2. 数据类型 3. 作用域 4. 生存期

  7. Ubuntu中NetBeans C/C++配置、编译

    系统环境:Ubuntu 9.04软件环境:NetBeans 6.7.1 C/C++ .JDK1.6.0_16本次目的:完成NetBeans 6.7.1 C/C++ 的配置工作.编译测试及对中文支持 首 ...

  8. ASP.NET MVC 学习第三天

    今天来简单说一下Razor视图引擎语法相关的和视图类. 添加一个MvcTest项目,继续添加一个Home控制器,完成index的视图添加.我们就在index这里分析razor视图引擎.下面是home控 ...

  9. 关于 iOS10 更新后 360 云盘 的上传按钮消失的解决方案

    最近出了iOS10,作为iOS开发者,果断更新. 但是更新完后,打开自己的360云盘,发现想向云盘上传东西,但是传不了,加号按钮不见了. 经过我的研究,原因是 下面的自定义tabbar放置加号按钮的方 ...

  10. easyui toolbar 可以放在datagrid底下

    html: <div class="easyui-tabs" style="height: 250px;" tools="#t_rank&quo ...