Bridge Pattern

桥接模式的实现与应用场景

问题

什么是桥接模式?如何在 JavaScript 中实现?

解答

桥接模式将抽象与实现分离,让两者可以独立变化。当一个类存在两个或多个独立变化的维度时,使用桥接模式可以避免类爆炸。

场景示例:消息发送系统

假设有不同类型的消息(普通、紧急)和不同的发送方式(邮件、短信),如果用继承会产生 4 个类,维度增加时类数量会爆炸。

// 实现部分:发送方式
class MessageSender {
  send(message) {
    throw new Error('子类必须实现 send 方法');
  }
}

class EmailSender extends MessageSender {
  send(message) {
    console.log(`通过邮件发送: ${message}`);
  }
}

class SmsSender extends MessageSender {
  send(message) {
    console.log(`通过短信发送: ${message}`);
  }
}

// 抽象部分:消息类型
class Message {
  constructor(sender) {
    // 桥接:持有实现部分的引用
    this.sender = sender;
  }

  send(content) {
    throw new Error('子类必须实现 send 方法');
  }
}

class NormalMessage extends Message {
  send(content) {
    this.sender.send(`[普通] ${content}`);
  }
}

class UrgentMessage extends Message {
  send(content) {
    this.sender.send(`[紧急!!!] ${content}`);
  }
}

// 使用
const emailSender = new EmailSender();
const smsSender = new SmsSender();

const normalEmail = new NormalMessage(emailSender);
normalEmail.send('会议通知');
// 输出: 通过邮件发送: [普通] 会议通知

const urgentSms = new UrgentMessage(smsSender);
urgentSms.send('服务器宕机');
// 输出: 通过短信发送: [紧急!!!] 服务器宕机

前端实际应用:主题 + 组件

// 实现部分:主题
class Theme {
  getStyles() {
    throw new Error('子类必须实现');
  }
}

class LightTheme extends Theme {
  getStyles() {
    return { background: '#fff', color: '#333' };
  }
}

class DarkTheme extends Theme {
  getStyles() {
    return { background: '#333', color: '#fff' };
  }
}

// 抽象部分:UI 组件
class UIComponent {
  constructor(theme) {
    this.theme = theme;
  }

  render() {
    throw new Error('子类必须实现');
  }
}

class Button extends UIComponent {
  render() {
    const styles = this.theme.getStyles();
    return `<button style="background:${styles.background};color:${styles.color}">按钮</button>`;
  }
}

class Input extends UIComponent {
  render() {
    const styles = this.theme.getStyles();
    return `<input style="background:${styles.background};color:${styles.color}" />`;
  }
}

// 使用:任意组合
const darkButton = new Button(new DarkTheme());
const lightInput = new Input(new LightTheme());

console.log(darkButton.render());
console.log(lightInput.render());

结构图

        抽象部分                    实现部分
    ┌───────────┐              ┌───────────┐
    │  Message  │──────────────│  Sender   │
    └─────┬─────┘              └─────┬─────┘
          │                          │
    ┌─────┴─────┐              ┌─────┴─────┐
    │           │              │           │
┌───────┐ ┌─────────┐    ┌─────────┐ ┌─────────┐
│Normal │ │ Urgent  │    │  Email  │ │   Sms   │
└───────┘ └─────────┘    └─────────┘ └─────────┘

关键点

  • 分离变化维度:将多个独立变化的维度拆分成独立的类层次
  • 组合优于继承:通过组合而非继承来扩展功能,避免类爆炸
  • 桥接引用:抽象部分持有实现部分的引用,运行时可动态切换
  • 适用场景:跨平台 UI、多主题系统、多数据源适配
  • 与策略模式区别:桥接强调结构分离,策略强调算法替换