门面模式(Facade):为子系统中的一组接口提供一个一致的界面,Facade 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
适用场景:
1、为一个复杂子系统提供一个简单接口时,由于子系统往往因为不断演化而变得越来越复杂,但这种变化不应该影响到客户的调用,此时使用 Facade 模式对外提供一个访问的接口;此外,还可以提供多个 Facade 类以实现不同的子系统的定制;
2、客户与抽象类的实现部分之间存在着很大的依赖性。用 Facade 模式将这个子系统与客户以及其他的子系统分离解耦,让客户通过 Facade 类来访问具体子系统,这样也能够保持各个子系统的独立性,即可重用;
3、构建一个层次结构的子系统时,使用 Facade 模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过 Facade 进行通讯,从而简化了它们之间的依赖关系。
通用类图:
Facade 模式类比数据库中的视图机制:
联系 Facade 模式的定义以及适用场景,发现与数据库中的视图机制非常类似。当我们不希望用户直接操作数据库中的一些表时,可以创建一些具有特定功能的视图,而且还可以针对不同的用户权限定义不同的视图操作功能。更重要的是,这些视图所对应的表可以进行修改,而视图却仍然可以工作。
Facade 模式以及数据库中的视图机制,我认为都是提供了一个中间层,以此不仅达到解耦的效果,还可以保证安全性,因为与用户进行通信的是 Facade 类或者是视图,真正的子系统或者表被隐藏在后面的一层当中了,用户不能够直接操作子系统或者表,当然也就修改不了了,安全性得到保障。
Facade 模式类比邮局的业务流程:
看着上面的类图,实在很简单,很难想象到底是怎么回事,就用一个生活中的具体例子来描述一下吧。平时我们寄信,都是写好正文装在信封中就投给邮局了,具体邮局是怎么完成业务的,我们作为服务的消费者并不知情,这就是一个类似的 Facade 模式,邮局对于我们消费者则是 Facade 门面。
假如邮局在其业务流程中需要增加一道特殊工序,那么在其内部只需要添加这一具体业务则可,用户并不知情。例如邮局推出给邮递员完成送信之后立刻给收信人送上一张节日贺卡的人性化服务(多好啊)。送信人可以在寄信时并不了解这一特殊服务,但信还是照样寄出去了,收信人也收到了,一个完整的工作流程就结束了。
注意:在以上例子中,一张张数据库表、一项项邮局推出的人性化服务都应该看作类图中的 Subsystem 子系统,它们是真正处理业务逻辑的对象,而不是由 Facade 来担任这一职责。
好吧,用代码实现一下:
- // 子系统01,邮局接收信件的业务
- class Subsystem01 {
- public void receiveLetters() {
- System.out.println("邮局接收用户的信件...");
- }
- }
- // 子系统02,邮局检查信件并分类的业务
- class Subsystem02 {
- public void checkLetters() {
- System.out.println("邮局检查用户的信件...");
- }
- }
- // 子系统03,邮局让邮递员送信给收信人
- class Subsystem03 {
- public void sendToReceiver() {
- System.out.println("邮递员送信 ...");
- }
- }
- // 子系统04,邮局新推出的赠送贺卡的特殊业务
- class Subsystem04 {
- public void sendGreetingCard() {
- System.out.println("邮局的额外送贺卡服务 ...");
- }
- }
- // Facade01 ,只是普通的送信
- class Facade01 {
- private Subsystem01 subsystem01;
- private Subsystem02 subsystem02;
- private Subsystem03 subsystem03;
- public Facade01() {
- this.subsystem01 = new Subsystem01();
- this.subsystem02 = new Subsystem02();
- this.subsystem03 = new Subsystem03();
- }
- // 普通的送信,委托给各个必要的子系统
- public void commonSendLetters() {
- this.subsystem01.receiveLetters();
- this.subsystem02.checkLetters();
- this.subsystem03.sendToReceiver();
- }
- }
- //Facade02 ,增加了送贺卡的业务
- class Facade02 {
- // 委托 Facade01 进行普通业务的处理
- private Facade01 facade01;
- private Subsystem04 subsystem04;
- public Facade02() {
- this.facade01 = new Facade01();
- this.subsystem04 = new Subsystem04();
- }
- // 特殊的送信
- public void specialSendLetters() {
- this.facade01.commonSendLetters();
- // 普通的送信之后再赠送贺卡
- this.subsystem04.sendGreetingCard();
- }
- }
- // 测试类,即客户寄信
- public class Client {
- public static void main(String[] args) {
- Facade01 facade01 = new Facade01();
- facade01.commonSendLetters();
- System.out.println();
- Facade02 facade02 = new Facade02();
- facade02.specialSendLetters();
- }
- }
- 邮局接收用户的信件...
- 邮局检查用户的信件...
- 邮递员送信 ...
- 邮局接收用户的信件...
- 邮局检查用户的信件...
- 邮递员送信 ...
- 邮局的额外送贺卡服务 ...