门面模式(Facade)类比数据库视图机制、邮局业务流程

门面模式(Facade):为子系统中的一组接口提供一个一致的界面,Facade 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

适用场景:

1、为一个复杂子系统提供一个简单接口时,由于子系统往往因为不断演化而变得越来越复杂,但这种变化不应该影响到客户的调用,此时使用 Facade 模式对外提供一个访问的接口;此外,还可以提供多个 Facade 类以实现不同的子系统的定制;

2、客户与抽象类的实现部分之间存在着很大的依赖性。用 Facade 模式将这个子系统与客户以及其他的子系统分离解耦,让客户通过 Facade 类来访问具体子系统,这样也能够保持各个子系统的独立性,即可重用;

3、构建一个层次结构的子系统时,使用 Facade 模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过 Facade 进行通讯,从而简化了它们之间的依赖关系。

通用类图:

 

门面模式(Facade)类比数据库视图机制、邮局业务流程_第1张图片  

Facade 模式类比数据库中的视图机制:

联系 Facade 模式的定义以及适用场景,发现与数据库中的视图机制非常类似。当我们不希望用户直接操作数据库中的一些表时,可以创建一些具有特定功能的视图,而且还可以针对不同的用户权限定义不同的视图操作功能。更重要的是,这些视图所对应的表可以进行修改,而视图却仍然可以工作。

Facade 模式以及数据库中的视图机制,我认为都是提供了一个中间层,以此不仅达到解耦的效果,还可以保证安全性,因为与用户进行通信的是 Facade 类或者是视图,真正的子系统或者表被隐藏在后面的一层当中了,用户不能够直接操作子系统或者表,当然也就修改不了了,安全性得到保障。

Facade 模式类比邮局的业务流程:

看着上面的类图,实在很简单,很难想象到底是怎么回事,就用一个生活中的具体例子来描述一下吧。平时我们寄信,都是写好正文装在信封中就投给邮局了,具体邮局是怎么完成业务的,我们作为服务的消费者并不知情,这就是一个类似的 Facade 模式,邮局对于我们消费者则是 Facade 门面。

假如邮局在其业务流程中需要增加一道特殊工序,那么在其内部只需要添加这一具体业务则可,用户并不知情。例如邮局推出给邮递员完成送信之后立刻给收信人送上一张节日贺卡的人性化服务(多好啊)。送信人可以在寄信时并不了解这一特殊服务,但信还是照样寄出去了,收信人也收到了,一个完整的工作流程就结束了。

注意:在以上例子中,一张张数据库表、一项项邮局推出的人性化服务都应该看作类图中的 Subsystem 子系统,它们是真正处理业务逻辑的对象,而不是由 Facade 来担任这一职责。

好吧,用代码实现一下:

  
  
  
  
  1. // 子系统01,邮局接收信件的业务 
  2. class Subsystem01 { 
  3.     public void receiveLetters() { 
  4.         System.out.println("邮局接收用户的信件..."); 
  5.     } 

  1. // 子系统02,邮局检查信件并分类的业务 
  2. class Subsystem02 { 
  3.     public void checkLetters() { 
  4.         System.out.println("邮局检查用户的信件..."); 
  5.     } 


      
      
      
      
  1. // 子系统03,邮局让邮递员送信给收信人 
  2. class Subsystem03 { 
  3.     public void sendToReceiver() { 
  4.         System.out.println("邮递员送信 ..."); 
  5.     } 

      
      
      
      
  1. // 子系统04,邮局新推出的赠送贺卡的特殊业务 
  2. class Subsystem04 { 
  3.     public void sendGreetingCard() { 
  4.         System.out.println("邮局的额外送贺卡服务 ..."); 
  5.     } 

      
      
      
      
  1. // Facade01 ,只是普通的送信 
  2. class Facade01 { 
  3.     private Subsystem01 subsystem01; 
  4.     private Subsystem02 subsystem02; 
  5.     private Subsystem03 subsystem03; 
  6.      
  7.     public Facade01() { 
  8.         this.subsystem01 = new Subsystem01(); 
  9.         this.subsystem02 = new Subsystem02(); 
  10.         this.subsystem03 = new Subsystem03(); 
  11.     } 
  12.      
  13.     // 普通的送信,委托给各个必要的子系统 
  14.     public void commonSendLetters() { 
  15.         this.subsystem01.receiveLetters(); 
  16.         this.subsystem02.checkLetters(); 
  17.         this.subsystem03.sendToReceiver(); 
  18.     }    

      
      
      
      
  1. //Facade02 ,增加了送贺卡的业务 
  2. class Facade02 { 
  3.  
  4.     // 委托 Facade01 进行普通业务的处理 
  5.     private Facade01 facade01; 
  6.     private Subsystem04 subsystem04; 
  7.      
  8.     public Facade02() { 
  9.         this.facade01 = new Facade01(); 
  10.         this.subsystem04 = new Subsystem04(); 
  11.     } 
  12.      
  13.     // 特殊的送信 
  14.     public void specialSendLetters() { 
  15.         this.facade01.commonSendLetters(); 
  16.         // 普通的送信之后再赠送贺卡 
  17.         this.subsystem04.sendGreetingCard(); 
  18.     } 

      
      
      
      
  1. // 测试类,即客户寄信 
  2. public class Client { 
  3.     public static void main(String[] args) { 
  4.         Facade01 facade01 = new Facade01(); 
  5.         facade01.commonSendLetters(); 
  6.          
  7.         System.out.println(); 
  8.          
  9.         Facade02 facade02 = new Facade02(); 
  10.         facade02.specialSendLetters(); 
  11.     } 

      
      
      
      
  1. 邮局接收用户的信件... 
  2. 邮局检查用户的信件... 
  3. 邮递员送信 ... 
  4.  
  5. 邮局接收用户的信件... 
  6. 邮局检查用户的信件... 
  7. 邮递员送信 ... 
  8. 邮局的额外送贺卡服务 ... 
在上面的邮局业务模拟中,我们在 Facade02 类中将邮局的普通业务委托给 Facade01 对象,然后才添加特殊的赠送贺卡服务,这就说明了不仅各个 Subsystem 类是可重用的,连 Facade 门面类也可以适当地进行重用,只要符合业务逻辑即可。这个重用也是委托,使得我们省去重新写相同代码的麻烦。
 
那么在这里我们可以扩展一下,如果一个 Subsystem 类中的业务功能太过庞大,那么我们可以设计多个 Facade 类,每一个都内置该 Subsystem 类中的某些业务,即拆分 Subsystem ,再提供一个 Facade 类来封装这些拆分出来的 Facade 类。
 
邮局再有什么特殊业务,扩展具体的 Subsystem 类即可,但是,这样的话就需要对原来的 Facade 进行修改了,或者再提供另一个 Facade 类,就像上面的 Facade02 类。
 
基本上,在 Facade 模式的通用类图中没有体现出 抽象,而我们的简单实现中也是如此。我认为,这是因为 Facade 模式旨在对客户提供一个访问入口、接口,具体内部的 Subsystem 子系统是否遵循了 抽象 的编程方法,这没有关系,只要客户是通过 Facade 来访问、获得 Subsystem 的功能、服务即可。
 
Facade 模式与 Mediator模式(中介者)的比较:
在 Facade 模式中,Facade 并不参与 Subsystem 类中的业务逻辑,所有的业务功能实际上全由各个 Subsystem 完成, Facade 只是在客户与 Subsystem 之间存在的一道门,客户只能拿着这道门的钥匙来获得业务功能、服务;
 
而在 Mediator模式中,Mediator类是一个调停者、中介者,它完完全全地负责协调各个 Colleague 同事类之间的信息交互,以此来完成其工作。
 
我的相关文章:
(Mediator)中介者模式的Java实现 http://haolloyin.blog.51cto.com/1177454/333810

 

你可能感兴趣的:(Decorator,Facade,外观模式,门面模式,中介者)