# Facade（外观模式）

Facade（外观模式）属于结构型模式，是一种日常开发中经常被使用到的设计模式。

**意图：为子系统中的一组接口提供一个一致的界面，Facade 模式定义了一个高层接口，这个接口使得这一子系统更加容易使用。**

## 举例子

如果看不懂上面的意图介绍，没有关系，设计模式需要在日常工作里用起来，结合例子可以加深你的理解，下面我准备了三个例子，让你体会什么场景下会用到这种设计模式。

## 意图解释

### 图书管理员

图书馆是一个非常复杂的系统，虽然图书按照一定规则摆放，但也只有内部人员比较清楚，作为一位初次来的访客，想要快速找到一本书，最好的办法是直接问图书管理员，而不是先了解这个图书馆的设计，因为你可能要来回在各个楼宇间奔走，借书的流程可能也比较长。

图书管理员就起到了简化图书馆子系统复杂度的作用，我们只要凡事询问图书管理员即可，而不需要关心他是如何与图书馆内部系统打交道的。

### 最多跑一次便民服务

浙江省推出的最多跑一次服务非常方便，很多办事流程都简化了，无论是证件办理还是业务受理，几乎只要跑一次，而必须要持续几天的流程也会通过手机短信或者 App 操作完成后续流程。

这就相当于外观模式，因为政府系统内部的办事流程可能没有太大变化，但通过抽象出 Facade（外观），让普通市民可以直接与便民办事处连接，而不需要在车管所与驾校之间来回奔波，背后的事情没有少，只是便民办事处帮你做了。

### Iphone 快捷指令功能

手机的 App 非常多，而我们需要了解每个功能在哪个 App 上才能运用自如，而快捷指令功能可以将 App 的某些功能单独提取出来，形成一套新的功能组，我们可以只接触到 “拍照” “付款” “计算”，而不用管背后是调用了支付宝还是微信、系统内置摄像机还是其他摄像 App，也不用关心这个 App 内部功能的入口在哪里，这些对接都在快接指令中自动完成。

快捷指令也是一种外观模式。

## 意图解释

**意图：为子系统中的一组接口提供一个一致的界面，Facade 模式定义了一个高层接口，这个接口使得这一子系统更加容易使用。**

为降低一个拥有多个接口的子系统内部复杂性，我们需要一个外观来屏蔽内部的复杂性，因此外观模式就是定义一个高层接口，这个接口直连子系统的内部实现，但调用这个高层接口的人不需要关心子系统内部的实现，这样，对于不想了解子系统内部实现的人来说，提高了易用度。

当然如果想要深度定制，就可以绕过外观模式，直接使用子系统提供的类，所以说并不是有了外观模式就必须通过外观调用，而是根据实际需要判断使用哪种调用方式。

## 结构图

<img width=600 src="https://img.alicdn.com/tfs/TB1j9gZ3.T1gK0jSZFrXXcNCXXa-1082-412.png">

可以看到，Facade 直接指向子系统中的类，**而子系统的类不会反向指向 Facade**。

## 代码例子

下面例子使用 typescript 编写。

```typescript
// 假设一个子系统是三个类结合使用的，为了抽象而解耦开了
class A {
  constructor(b: B) {
    this.b = b
  }
}

class B {
  constructor(c: C) {
    this.c = c
  }
}

class C {
  
}

// 它们组合成了一种常用功能，我们可以使用外观模式屏蔽子类的细节直接使用
class Compile {
  public run() {
    const parser = new A(new B(new C))
    parser.run()
  }
}

const compile = new Compile()
compile.run()
```

这样我们只要知道 `Compile` 类就可以了，而不需要了解背后的 `A` `B` `C` 以及其组合关系。

## 弊端

外观模式并不适合于所有场景，当子系统足够易用时，再使用外观模式就是画蛇添足。

另外，当系统难以抽象出通用功能时，外观模式的设计可能也无所适从，因为设计的高层接口可能适用范围很窄，此时外观模式的意义就比较小。

## 总结

其实抽象工厂模式也可以代替外观模式，来实现隐藏子类具体实现的效果，但外观模式描述更具有通用性。

> 讨论地址是：[精读《设计模式 - Facade 外观模式》· Issue #288 · dt-fe/weekly](https://github.com/dt-fe/weekly/issues/288)

**如果你想参与讨论，请 [点击这里](https://github.com/dt-fe/weekly)，每周都有新的主题，周末或周一发布。前端精读 - 帮你筛选靠谱的内容。**

> 关注 **前端精读微信公众号**

<img width=200 src="https://img.alicdn.com/tfs/TB165W0MCzqK1RjSZFLXXcn2XXa-258-258.jpg">

> 版权声明：自由转载-非商用-非衍生-保持署名（[创意共享 3.0 许可证](https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh)）
