Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.(要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。)

引子

“知道怎么把大象装进冰箱里面么?”(作者按:这么简单的问题还想考我,早了几百年吧。)

“把大象装进冰箱里,一共需要三步:第一步,把冰箱门打开;第二步,把大象装进去,第三步,把冰箱门关上。”(此处模仿本山老师语调,请自行脑补)

“恭喜你,回答正确,那么问题来了,要是有一万个大象是不是要走3万步呢?如果有顺序错了是不是就无法正确的装进去了呢?”

为了解决这个问题,我-外观模式也就应运而生了。

外观模式介绍

Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.翻译过来的意思是:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。外观模式提供了一个高层次的接口,使得子系统更易于使用。

我比较主要“统一的对象”,也就是提供一个访问子系统的接口,除了这个接口不允许有任何访问子系统的行为发生,通用类图如下所示:

客户程序通过发送请求给Facade的方式与子系统通讯,Facade将这些消息转发给适当的子系统对象,尽管子系统中有关对象在做实际工作,但我也必须将他的接口转换成子系统的接口。

外观模式分析

优点:

  • 减少系统的相互依赖。如果不适用我,那么外界将直接访问到系统内部,相互之间是强耦合,你问强耦合怎么了?我告诉你,强耦合就是同生共死,What?你说很浪漫?No,No,No,强依赖在系统设计中式不被接受的。所以你如果看到了,那说明你离重构不远矣~

  • 提高了灵活性。依赖少了,灵活性自然提高,无论系统内部如何变化,只要不影响到外观对象,我自岿然不动。

  • 提高了安全性。想让你访问那些业务就开通哪些逻辑,若不开通,若想访问,窗户都没有。

缺点:

  • 所谓的缺点就是不符合开闭原则,对扩展开放,对修改关闭。想想我们的实现,在投入使用后若发现门面对象错了,就无法再解决了,唯有修改门面的角色代码,这个风险么,不需要我多说了。

外观模式之实现

既然说到了大象,那就以大象为题,实现以下罢了~首先是子系统:

第一步,开冰箱门的子系统: 

public class A{
    public void open(){
        System.out.println("把冰箱门打开");
    }
}

第二步,把大象装进去的子系统:

public class B{
    public void pack(){
        System.out.println("把大象装进去");
    }
}

第三步,把冰箱门关上的子系统:

public class C{
    public void close(){
        System.out.println("把冰箱门关上");
    }
}

由于此三个类是处理的相关业务,也就是说其实是一个子系统的不同的逻辑处理模块,对于此类子系统的访问可以通过下面的外观进行访问,外观对象代码如下:

public class Facade{
    //被委托的对象
    private A a = new A();
    private B b = new B();
    private C c = new C();

    //提供外部访问的方法
    public void methodA{
        this.a.open();
        this.b.pack();
        this.c.close();
    }

}

至此,外观模式的实现就完成了,以后把大象装进冰箱不用再一步一步的来,直接调用Facade的方法,即可一步到位,麻麻再也不用担心步骤不对了~

外观模式之应用场景

  • 当要为一个复杂的子系统提供一个简单的接口的时候。
  • 当客户程序与抽象类实现部分之间存在很大依赖性的时候。
  • 当需要构建一个层次结构的子系统的时候。

遇到以上三种情况时,你就可以考虑使用外观模式了。

完毕。