TypeScript设计模式(7):外观模式

84 阅读3分钟

1. 什么是外观模式?

外观模式(Facade Pattern) 是一种 结构型设计模式,它提供了一个简化的接口,以隐藏系统的复杂性。外观模式为多个复杂的子系统提供一个统一的接口,使客户端代码无需直接与这些子系统交互,而是通过外观类进行操作。

2. 为什么要使用外观模式?

在实际开发中,系统可能由多个子模块组成,而直接操作这些模块可能会带来以下问题:

  • 代码复杂度高,难以维护
  • 需要深入理解每个子系统的内部逻辑
  • 客户端代码与多个子系统耦合,影响灵活性

通过 外观模式,我们可以 封装复杂的子系统,使客户端代码更简洁、更易用。

3. TypeScript 实现外观模式

假设我们正在开发一个 家庭影院系统,该系统由多个子模块组成,如 DVD 播放器、音响、灯光和投影仪。我们可以使用外观模式来提供一个简化的接口。

3.1 子系统类

// DVD 播放器
class DVDPlayer {
    on() { console.log("DVD 播放器已开启"); }
    off() { console.log("DVD 播放器已关闭"); }
    play(movie: string) { console.log(`正在播放电影: ${movie}`); }
}

// 音响
class SoundSystem {
    on() { console.log("音响已开启"); }
    off() { console.log("音响已关闭"); }
    setVolume(level: number) { console.log(`音量已调至: ${level}`); }
}

// 灯光
class Lights {
    dim(level: number) { console.log(`灯光亮度设置为: ${level}`); }
}

// 投影仪
class Projector {
    on() { console.log("投影仪已开启"); }
    off() { console.log("投影仪已关闭"); }
    setMode(mode: string) { console.log(`投影仪模式设置为: ${mode}`); }
}

3.2 创建外观类

class HomeTheaterFacade {
    private dvdPlayer: DVDPlayer;
    private soundSystem: SoundSystem;
    private lights: Lights;
    private projector: Projector;

    constructor(dvdPlayer: DVDPlayer, soundSystem: SoundSystem, lights: Lights, projector: Projector) {
        this.dvdPlayer = dvdPlayer;
        this.soundSystem = soundSystem;
        this.lights = lights;
        this.projector = projector;
    }

    watchMovie(movie: string) {
        console.log("准备播放电影...");
        this.lights.dim(10);
        this.projector.on();
        this.projector.setMode("影院模式");
        this.soundSystem.on();
        this.soundSystem.setVolume(8);
        this.dvdPlayer.on();
        this.dvdPlayer.play(movie);
        console.log("电影播放开始!");
    }

    endMovie() {
        console.log("关闭家庭影院系统...");
        this.dvdPlayer.off();
        this.soundSystem.off();
        this.projector.off();
        this.lights.dim(100);
        console.log("影院模式已退出。");
    }
}

3.3 客户端调用

// 创建子系统组件
const dvdPlayer = new DVDPlayer();
const soundSystem = new SoundSystem();
const lights = new Lights();
const projector = new Projector();

// 创建外观对象
const homeTheater = new HomeTheaterFacade(dvdPlayer, soundSystem, lights, projector);

// 使用外观模式播放电影
homeTheater.watchMovie("哪吒2");

// 结束电影
homeTheater.endMovie();

4. 外观模式的优缺点

4.1 优点

简化接口:提供统一的 API,隐藏子系统的复杂性。 ✅ 降低耦合:客户端代码与多个子系统解耦,提高灵活性。 ✅ 提高可维护性:更容易管理和扩展系统。

4.2 缺点

可能造成不必要的封装:如果子系统本身已经足够简单,使用外观模式可能会增加额外的代码量。 ❌ 降低灵活性:外观模式提供的是固定的 API,可能无法满足所有的自定义需求。

5. 适用场景

  • 需要提供简单的接口给客户端,而隐藏复杂的实现细节。
  • 需要解耦多个子系统,降低系统复杂度。
  • 适用于 大型系统,如 框架、SDK 设计、复杂业务系统 等。

6. 总结

外观模式 通过 封装多个子系统的复杂性,提供一个 简单、统一的接口,从而 降低耦合提高可维护性。在 TypeScript 开发中,它可以广泛应用于 模块化架构设计、API 设计、前端 UI 组件封装 等场景,使代码更加清晰和易于管理。