前言

这是关于设计模式的系列文章,在每篇文章中将对常见设计模式进行讲解,因为针对前端方向,而且前端常用语言 JavaScript 本身是弱类型,面向对象(模拟面向对象)编程的实现相较于其他强类型语言实现更为繁琐,所以代码主要以 JavaScript 表现。

系列文章链接:

外观模式简介

“外观模式” 就是把一些复杂的流程封装成一个接口,提供给外部更简单的使用。

在外观模式中存在三种角色如下:

  • 门面角色(Facade):是 “外观模式” 的核心,它熟悉子系统的功能,并被客户角色调用,内部实现了客户角色需求功能的组合;
  • 子系统角色(System):实现了子系统的功能(多个),对于客户角色是未知的;
  • 客户角色(Client):通过调用 Facede 来完成要实现的功能。


外观模式 UML 图
外观模式 UML 图


外观模式的实现

上面已经介绍了 “外观模式” 的各个角色,下面是简单的代码实现。

// 子系统角色 Sum
class Sum {
  sum(a, b) {
    return a + b;
  }
}

// 子系统角色 Minus
class Minus {
  minus(a, b) {
    return a - b;
  }
}

// 子系统角色 Multipy
class Multipy {
  multipy(a, b) {
    return a * b;
  }
}

// 子系统角色 Divide
class Divide {
  divide(a, b) {
    return a / b;
  }
}

// 门面角色 Calculator
class Calculator {
  constructor() {
    this.sumObj = new Sum();
    this.minusObj = new Minus();
    this.multipyObj = new Multipy();
    this.divideObj = new Divide();
  }
  sum(...args) {
    return this.sumObj.sum(...args);
  }
  minus(...args) {
    return this.minusObj.minus(...args);
  }
  multipy(...args) {
    return this.multipyObj.multipy(...args);
  }
  divide(...args) {
    return this.divideObj.divide(...args);
  }
}

// 客户角色
const calculator = new Calculator();

console.log(calculator.sum(1, 2)); // 3
console.log(calculator.minus(1, 2)); // -1
console.log(calculator.multipy(1, 2)); // 2
console.log(calculator.divide(1, 2)); // 0.5

我们在上面代码中实现了一个计算器功能,计算器具备的功能为加、减、乘、除,我们把这四个功能分别拆分成为四个子系统,用门面类 Calculator 来进行连接,这样只需要调用 Calculator 的实例(客户角色)就可以调用四个子系统模块分别提供的功能,但是上面的代码实现功能比较简洁,并没达到 “外观模式” 的真正作用,就是可以随意组合各个子系统的功能。

/* 组合子系统功能 */
// 子系统角色 CPU
class CPU {
  start() {
    console.log('CPU 启动');
  }
}

// 子系统角色 Memory
class Memory {
  start() {
    console.log('内存启动');
  }
}

// 子系统角色 Disk
class Disk {
  start() {
    console.log('硬盘启动');
  }
}

// 门面角色 Computer
class Computer {
  constructor() {
    this.cpu = new CPU();
    this.memory = new Memory();
    this.disk = new Disk();
  }
  start() {
    // 组合子系统功能
    this.cpu.start();
    this.memory.start();
    this.disk.start();
  }
}

// 客户角色
const computer = new Computer();

computer.start();
// CPU 启动
// 内存启动
// 硬盘启动

上面代码打印了一个计算机的启动过程,功能来自于各个子系统,也可以通过门面角色实现子系统功能的多种组合。

总结

“外观模式” 的作用是可以对复杂功能解耦合,分散到各个子系统,使子系统与子系统互相独立,并对各个子系统提供外界访问的功能组合模块,这样既提高了子系统的维护性,又增加了外界访问功能的扩展性,最后附上 案例地址