介绍

对于这个模式有两种不同的理解方式。在 GoF 的《设计模式》一书中,桥接模式被定义为:“将抽象和实现解耦,让它们可以独立变化。”在其他资料和书籍中,还有另外一种更加简单的理解方式:“一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。”

对于第一种 GoF 的理解方式,弄懂定义中“抽象”和“实现”两个概念,是理解它的关键。定义中的“抽象”,指的并非“抽象类”或“接口”,而是被抽象出来的一套“类库”,它只包含骨架代码,真正的业务逻辑需要委派给定义中的“实现”来完成。而定义中的“实现”,也并非“接口的实现类”,而是一套独立的“类库”。“抽象”和“实现”独立开发,通过对象之间的组合关系,组装在一起。

对于第二种理解方式,它非常类似我们之前讲过的“组合优于继承”设计原则,通过组合关系来替代继承关系,避免继承层次的指数级爆炸

代码实现


  /// <summary>
  /// 游戏中常见的例子:
  /// 
  // 角色使用不同的武器攻击敌人
  // 角色有不同类型(如战士、法师)
  // 武器也有不同类型(如剑、魔法杖)
  // 角色和武器是独立变化的
  /// </summary>
  public class Bridge
  {
      static void Main()
      {
          IWeapon sword = new Sword();
          IWeapon magicWand = new MagicWand();
          Character character= new Warrior(magicWand);
          character.Attack();

          Character shoote= new Shooter(magicWand);
          shoote.Attack();
      }
  }

  public interface IWeapon
  {
      void Attack();
  }

  // 具体武器
  public class Sword : IWeapon
  {
      public void Attack()
      {
          Console.WriteLine("用剑劈砍");
      }
  }

  public class MagicWand : IWeapon
  {

      public void Attack()
      {
         Console.WriteLine("用魔法释放火球");
      }
  }

  // 角色抽象类
  public abstract class Character
  {
      protected IWeapon weapon;

      public Character(IWeapon weapon)
      {
          this.weapon =  weapon;
      } 

      public abstract void Attack();
  }

  // 具体角色

  public class Warrior : Character
  {
      public Warrior(IWeapon weapon) : base(weapon) {}

      public override void Attack()
      {
          Console.WriteLine("战士 :");
          weapon.Attack();
      }
  }

  public class Shooter : Character
  {
      public Shooter(IWeapon weapon) : base(weapon) {}

      public override void Attack()
      {
          Console.WriteLine("射手 :");
          weapon.Attack();
      }
  }

问题 1:桥接模式是否要求“一方是抽象,一方是具体”?

✅ 回答:

桥接模式并不是一方是抽象,另一方必须是具体。它的核心目的是:

“将抽象(Abstraction)与实现(Implementor)解耦,使两者可以独立扩展。”

🧠 分析你代码中的结构:

概念

代码中的角色

抽象 Abstraction

Character(角色抽象类)

扩展抽象 Refined Abstraction

Warrior, Shooter(不同类型角色)

实现 Implementor

IWeapon(武器接口)

具体实现 ConcreteImplementor

Sword, MagicWand(不同武器)

因此,这个结构完全符合桥接模式:

  • 抽象部分:角色系统可以扩展出 Warrior、Shooter...

  • 实现部分:武器系统可以扩展出 Sword、MagicWand...

  • 它们通过组合(而不是继承)来解耦角色与武器的绑定关系。

👉 所以两边都有继承层次是正常且必要的,桥接的意思是:抽象层(角色)通过接口持有实现层(武器),解耦了两者的耦合。

问题 2:桥接模式将 x×y 的组合复杂度降为 x+y,在哪体现?

✅ 回答:

这正是桥接模式最大的价值:避免类爆炸。

📈 假如没有桥接,你可能需要写很多类:

比如你有:

  • 3个角色类型:Warrior、Shooter、Mage

  • 3种武器:Sword、MagicWand、Bow

🧨 不使用桥接的传统写法:

你可能需要组合出以下 9 个类:

  • WarriorWithSword

  • WarriorWithMagicWand

  • WarriorWithBow

  • ShooterWithSword

  • ShooterWithMagicWand

  • ...
    这就是 x × y = 3 × 3 = 9 个类

✅ 使用桥接模式之后:

  • 你只需要维护:

    • 3个角色子类(Warrior, Shooter, Mage

    • 3个武器子类(Sword, MagicWand, Bow

角色和武器可以 自由组合,你只需 x + y = 6 个类,在运行时组装即可:

Character shooter = new Shooter(new Bow()); 
Character mage = new Mage(new MagicWand());

这就是桥接模式“将类爆炸问题从乘法降到加法”的体现!