設計模式(15)-Facade Pattern

 -----------http://www.cnblogs.com/zhenyulu/articles/55992.html

一、 門面(Facade)模式

外部與一個子系統的通信必須通過一個統一的門面(Facade)對象進行,這就是門面模式。

醫院的例子

用一個例子進行說明,如果把醫院作爲一個子系統,按照部門職能,這個系統可以劃分爲掛號、門診、劃價、化驗、收費、取藥等。看病的病人要與這些部門打交道,就如同一個子系統的客戶端與一個子系統的各個類打交道一樣,不是一件容易的事情。

首先病人必須先掛號,然後門診。如果醫生要求化驗,病人必須首先劃價,然後繳款,才能到化驗部門做化驗。化驗後,再回到門診室。

解決這種不便的方法便是引進門面模式。可以設置一個接待員的位置,由接待員負責代爲掛號、劃價、繳費、取藥等。這個接待員就是門面模式的體現,病人只接觸接待員,由接待員負責與醫院的各個部門打交道。

什麼是門面模式

門面模式要求一個子系統的外部與其內部的通信必須通過一個統一的門面(Facade)對象進行。門面模式提供一個高層次的接口,使得子系統更易於使用。

就如同醫院的接待員一樣,門面模式的門面類將客戶端與子系統的內部複雜性分隔開,使得客戶端只需要與門面對象打交道,而不需要與子系統內部的很多對象打交道。


二、 門面模式的結構

門面模式是對象的結構模式。門面模式沒有一個一般化的類圖描述,下圖演示了一個門面模式的示意性對象圖:

 Pic90.gif

在這個對象圖中,出現了兩個角色:

門面(Facade)角色:客戶端可以調用這個角色的方法。此角色知曉相關的(一個或者多個)子系統的功能和責任。在正常情況下,本角色會將所有從客戶端發來的請求委派到相應的子系統去。

子系統(subsystem)角色:可以同時有一個或者多個子系統。每一個子系統都不是一個單獨的類,而是一個類的集合。每一個子系統都可以被客戶端直接調用,或者被門面角色調用。子系統並不知道門面的存在,對於子系統而言,門面僅僅是另外一個客戶端而已。


三、 門面模式的實現

一個系統可以有幾個門面類

【GOF】的書中指出:在門面模式中,通常只需要一個門面類,並且此門面類只有一個實例,換言之它是一個單例類。當然這並不意味着在整個系統裏只能有一個門面類,而僅僅是說對每一個子系統只有一個門面類。或者說,如果一個系統有好幾個子系統的話,每一個子系統有一個門面類,整個系統可以有數個門面類。

爲子系統增加新行爲

初學者往往以爲通過繼承一個門面類便可在子系統中加入新的行爲,這是錯誤的。門面模式的用意是爲子系統提供一個集中化和簡化的溝通管道,而不能向子系統加入新的行爲。


四、 在什麼情況下使用門面模式

  • 爲一個複雜子系統提供一個簡單接口
  • 提高子系統的獨立性
  • 在層次化結構中,可以使用Facade模式定義系統中每一層的入口。


五、 一個例子

我們考察一個保安系統的例子,以說明門面模式的功效。一個保安系統由兩個錄像機、三個電燈、一個遙感器和一個警報器組成。保安系統的操作人員需要經常將這些儀器啓動和關閉。

不使用門面模式的設計

首先,在不使用門面模式的情況下,操作這個保安系統的操作員必須直接操作所有的這些部件。下圖所示就是在不使用門面模式的情況下系統的設計圖。

 Pic88.gif


可以看出,Client對象需要引用到所有的錄像機(Camera)、電燈(Light)、感應器(Sensor)和警報器(Alarm)對象。代碼如下:

None.gifusing System;
None.gif
None.gif
public class Camera
ExpandedBlockStart.gif
{
InBlock.gif  
public void TurnOn()
ExpandedSubBlockStart.gif  
{
InBlock.gif    Console.WriteLine(
"Turning on the camera.");
ExpandedSubBlockEnd.gif  }

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

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

ExpandedBlockEnd.gif}

None.gif
None.gif
public class Light
ExpandedBlockStart.gif
{
InBlock.gif
InBlock.gif  
public void TurnOff()
ExpandedSubBlockStart.gif  
{
InBlock.gif    Console.WriteLine(
"Turning on the light.");
ExpandedSubBlockEnd.gif  }

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

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

ExpandedBlockEnd.gif}

None.gif
None.gif
public class Sensor
ExpandedBlockStart.gif
{
InBlock.gif  
public void Activate()
ExpandedSubBlockStart.gif  
{
InBlock.gif    Console.WriteLine(
"Activating the sensor.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void Deactivate()
ExpandedSubBlockStart.gif  
{
InBlock.gif    Console.WriteLine(
"Deactivating the sensor.");
ExpandedSubBlockEnd.gif  }

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

ExpandedBlockEnd.gif}

None.gif
None.gif
public class Alarm
ExpandedBlockStart.gif
{
InBlock.gif
InBlock.gif  
public void Activate()
ExpandedSubBlockStart.gif  
{
InBlock.gif    Console.WriteLine(
"Activating the alarm.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void Deactivate()
ExpandedSubBlockStart.gif  
{
InBlock.gif    Console.WriteLine(
"Deactivating the alarm.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void Ring()
ExpandedSubBlockStart.gif  
{
InBlock.gif    Console.WriteLine(
"Ringing the alarm.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void StopRing()
ExpandedSubBlockStart.gif  
{
InBlock.gif    Console.WriteLine(
"Stop the alarm.");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
public class Client
ExpandedBlockStart.gif
{
InBlock.gif  
private static Camera camera1, camera2;
InBlock.gif  
private static Light light1, light2, light3;
InBlock.gif  
private static Sensor sensor;
InBlock.gif  
private static Alarm alarm;
InBlock.gif
InBlock.gif  
static Client()
ExpandedSubBlockStart.gif  
{
InBlock.gif    camera1 
= new Camera();
InBlock.gif    camera2 
= new Camera();
InBlock.gif    light1 
= new Light();
InBlock.gif    light2 
= new Light();
InBlock.gif    light3 
= new Light();
InBlock.gif    sensor 
= new Sensor();
InBlock.gif    alarm 
= new Alarm();
ExpandedSubBlockEnd.gif  }
  
InBlock.gif
InBlock.gif  
public static void Main( string[] args )
ExpandedSubBlockStart.gif  
{
InBlock.gif    camera1.TurnOn();
InBlock.gif    camera2.TurnOn();
InBlock.gif    light1.TurnOn();
InBlock.gif    light2.TurnOn();
InBlock.gif    light3.TurnOn();
InBlock.gif    sensor.Activate();
InBlock.gif    alarm.Activate();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

 

六、 使用門面模式的設計

一個合情合理的改進方法就是準備一個系統的控制檯,作爲保安系統的用戶界面。如下圖所示:

 Pic89.gif

程序代碼如下:

None.gifusing System;
None.gif
None.gif
public class Camera
ExpandedBlockStart.gif
dot.gif{
InBlock.gif  
public void TurnOn()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"Turning on the camera.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void TurnOff()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"Turning off the camera.");
ExpandedSubBlockEnd.gif  }

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

ExpandedBlockEnd.gif}

None.gif
None.gif
public class Light
ExpandedBlockStart.gif
dot.gif{
InBlock.gif
InBlock.gif  
public void TurnOff()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"Turning on the light.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void TurnOn()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"Turning off the light.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void ChangeBulb()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"changing the light-bulb.");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
public class Sensor
ExpandedBlockStart.gif
dot.gif{
InBlock.gif  
public void Activate()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"Activating the sensor.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void Deactivate()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"Deactivating the sensor.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void Trigger()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"The sensor has triggered.");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
public class Alarm
ExpandedBlockStart.gif
dot.gif{
InBlock.gif
InBlock.gif  
public void Activate()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"Activating the alarm.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void Deactivate()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"Deactivating the alarm.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void Ring()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"Ringing the alarm.");
ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
public void StopRing()
ExpandedSubBlockStart.gif  
dot.gif{
InBlock.gif    Console.WriteLine(
"Stop the alarm.");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
public class SecurityFacade
ExpandedBlockStart.gif
{
InBlock.gif  
private static Camera camera1, camera2;
InBlock.gif  
private static Light light1, light2, light3;
InBlock.gif  
private static Sensor sensor;
InBlock.gif  
private static Alarm alarm;
InBlock.gif
InBlock.gif  
static SecurityFacade()
ExpandedSubBlockStart.gif  
{
InBlock.gif    camera1 
= new Camera();
InBlock.gif    camera2 
= new Camera();
InBlock.gif    light1 
= new Light();
InBlock.gif    light2 
= new Light();
InBlock.gif    light3 
= new Light();
InBlock.gif    sensor 
= new Sensor();
InBlock.gif    alarm 
= new Alarm();
ExpandedSubBlockEnd.gif  }

InBlock.gif  
InBlock.gif  
public void Activate()
ExpandedSubBlockStart.gif  
{
InBlock.gif    camera1.TurnOn();
InBlock.gif    camera2.TurnOn();
InBlock.gif    light1.TurnOn();
InBlock.gif    light2.TurnOn();
InBlock.gif    light3.TurnOn();
InBlock.gif    sensor.Activate();
InBlock.gif    alarm.Activate();
ExpandedSubBlockEnd.gif  }

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

ExpandedBlockEnd.gif}

None.gif
None.gif
public class Client
ExpandedBlockStart.gif
{
InBlock.gif  
private static SecurityFacade security;
InBlock.gif
InBlock.gif  
public static void Main( string[] args )
ExpandedSubBlockStart.gif  
{
InBlock.gif    security 
= new SecurityFacade();
InBlock.gif    security.Activate();
InBlock.gif    Console.WriteLine(
"/n--------------------/n");
InBlock.gif    security.Deactivate();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

 


參考文獻:
閻宏,《Java與模式》,電子工業出版社
[美]James W. Cooper,《C#設計模式》,電子工業出版社
[美]Alan Shalloway  James R. Trott,《Design Patterns Explained》,中國電力出版社
[美]Robert C. Martin,《敏捷軟件開發-原則、模式與實踐》,清華大學出版社
[美]Don Box, Chris Sells,《.NET本質論 第1卷:公共語言運行庫》,中國電力出版社

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章