什么是外观模式?

外观模式(Facade Pattern)是一种结构型设计模式,它为复杂子系统提供一个统一的高层接口,使子系统更易于使用。客户端模式通过封装子系统的内部复杂性,对外暴露简单的调用入口,让客户端无需关心子系统的具体实现和交互细节,只需调用外观接口即可完成操作。

外观模式的核心角色

  1. 外观角色(Facade):封装子系统的复杂逻辑,提供简洁的接口供客户端调用,内部协调多个子系统的交互。
  2. 子系统角色(Subsystem):由多个具体功能模块组成,实现子系统的具体功能,对子系统的外部(包括外观角色)无感知。
  3. 客户端(Client):通过调用外观角色的接口使用子系统功能,无需直接与子系统交互。

JavaScript 实现外观模式示例:智能家居控制系统

以下以 “智能家居控制” 为例,实现外观模式。场景是:一个智能家居系统包含灯光、空调、电视等多个子系统,用户希望通过一个 “一键控制” 接口实现 “离家模式”(关闭所有设备)或 “回家模式”(开启指定设备),而无需逐个操作每个子系统。

代码实现 - javascript
// -------------- 1. 子系统角色:各智能设备 --------------
// 灯光子系统
class Light {
  // 开灯
  turnOn() {
    console.log("灯光已开启");
  }

  // 关灯
  turnOff() {
    console.log("灯光已关闭");
  }
}

// 空调子系统
class AirConditioner {
  // 开空调(默认26度)
  turnOn(temperature = 26) {
    console.log(`空调已开启,温度设置为 ${temperature}℃`);
  }

  // 关空调
  turnOff() {
    console.log("空调已关闭");
  }
}

// 电视子系统
class TV {
  // 开电视
  turnOn() {
    console.log("电视已开启");
  }

  // 关电视
  turnOff() {
    console.log("电视已关闭");
  }
}

// 窗帘子系统
class Curtain {
  // 打开窗帘
  open() {
    console.log("窗帘已打开");
  }

  // 关闭窗帘
  close() {
    console.log("窗帘已关闭");
  }
}

// -------------- 2. 外观角色:智能家居控制中心 --------------
class SmartHomeFacade {
  constructor() {
    // 初始化子系统(外观内部持有子系统实例)
    this.light = new Light();
    this.ac = new AirConditioner();
    this.tv = new TV();
    this.curtain = new Curtain();
  }

  // 回家模式:开启常用设备
  homeMode() {
    console.log("=== 启动回家模式 ===");
    this.light.turnOn(); // 开灯光
    this.ac.turnOn(25); // 开空调(25度)
    this.curtain.open(); // 开窗帘
  }

  // 离家模式:关闭所有设备
  awayMode() {
    console.log("=== 启动离家模式 ===");
    this.light.turnOff(); // 关灯光
    this.ac.turnOff(); // 关空调
    this.tv.turnOff(); // 关电视
    this.curtain.close(); // 关窗帘
  }

  // 观影模式:协调灯光、电视、窗帘
  movieMode() {
    console.log("=== 启动观影模式 ===");
    this.light.turnOff(); // 关灯光
    this.tv.turnOn(); // 开电视
    this.curtain.close(); // 关窗帘
    this.ac.turnOn(24); // 开空调(24度)
  }
}

// -------------- 3. 客户端使用 --------------
// 创建外观对象(控制中心)
const smartHome = new SmartHomeFacade();

// 调用外观接口,无需关心子系统细节
smartHome.homeMode();
// 输出:
// === 启动回家模式 ===
// 灯光已开启
// 空调已开启,温度设置为 25℃
// 窗帘已打开

smartHome.movieMode();
// 输出:
// === 启动观影模式 ===
// 灯光已关闭
// 电视已开启
// 窗帘已关闭
// 空调已开启,温度设置为 24℃

smartHome.awayMode();
// 输出:
// === 启动离家模式 ===
// 灯光已关闭
// 空调已关闭
// 电视已关闭
// 窗帘已关闭

代码说明

  1. 子系统角色LightAirConditioner 等类分别实现了单个设备的功能(如开关、调温),它们是系统的基础模块,但单独使用时需要客户端逐个操作,流程繁琐。
  2. 外观角色(SmartHomeFacade
    • 内部初始化所有子系统实例,封装了子系统的交互逻辑(如 “回家模式” 需要依次开灯、开空调、开窗帘)。
    • 对外提供 homeModeawayMode 等高层接口,客户端只需调用这些接口,即可完成复杂操作。
  3. 客户端:通过外观对象的简单接口使用系统,无需知道子系统的存在,也无需关心设备的调用顺序。

外观模式的优势

  • 简化使用:隐藏子系统的复杂性,客户端通过简洁接口即可完成操作,降低学习和使用成本。
  • 降低耦合:客户端与子系统解耦,子系统内部的修改(如换用其他品牌的灯光)不会影响客户端。
  • 便于维护:子系统的交互逻辑集中在外观类中,修改流程只需调整外观类,无需修改多个客户端。

常见应用场景

  • 复杂 API 封装:如浏览器兼容性处理(用外观模式封装不同浏览器的 API 差异,对外提供统一接口)。
  • 框架入口:如 jQuery 的 $ 函数(封装了 DOM 操作、事件处理等复杂逻辑,提供简单调用方式)。
  • 服务整合:如后端接口聚合(用外观模式整合多个微服务的接口,向前端提供一个统一接口)。

外观模式的核心是 “封装复杂性,提供简单入口”,尤其适合子系统复杂且需要频繁被外部使用的场景。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐