Skip to content

Head First 设计模式 15-桥接模式

🏷️ 《Head First 设计模式》

桥接模式 通过将 实现抽象 放在 两个不同的类层次 中而使它们 可以独立改变

书中以遥控器和电视为例:不同按键模式的遥控器来遥控不同品牌的电视。其类图如下:

RemoteControl 抽象类 和 TV 接口及其实现类 两个层次之间的关系,就叫做 桥接

优点

  • 将实现予以解耦,让它和界面之间不再永久绑定。
  • 抽象和实现可以独立扩展,不会影响到对方。
  • 对于“具体的抽象类”所做的改变,不会影响到客户。

用途和缺点

  • 适合使用在需要跨越多个平台的图形和窗口系统中。
  • 当需要用不同的方式改变接口和实现时,你会发现桥接模式很好用。
  • 桥接模式的缺点是增加了复杂度。

示例代码

TV

电视接口

csharp
interface TV
{
    void On();
    void Off();
    void TurnChannel(int channel);
}

MiTV

小米电视类

csharp
class MiTV : TV
{
    public void Off()
    {
        Console.WriteLine("You turned off the MiTV.");
    }

    public void On()
    {
        Console.WriteLine("You turned on the MiTV.");
    }

    public void TurnChannel(int channel)
    {
        Console.WriteLine($"You turned the MiTV's channel to {channel}.");
    }
}

LeTV

乐视电视类

csharp
class LeTV : TV
{
    public void Off()
    {
        Console.WriteLine("You turned off the LeTV.");
    }

    public void On()
    {
        Console.WriteLine("You turned on the LeTV.");
    }

    public void TurnChannel(int channel)
    {
        Console.WriteLine($"You turned the LeTV's channel to {channel}.");
    }
}

RemoteControl

遥控器抽象类

csharp
abstract class RemoteControl
{
    private TV _tv;

    public RemoteControl(TV tv)
    {
        _tv = tv;
    }

    public void On()
    {
        _tv.On();
    }
    public void Off()
    {
        _tv.Off();
    }

    protected void SetChannel(int channel)
    {
        _tv.TurnChannel(channel);
    }
}

ConcreteRemote

具体的遥控器实现

csharp
class ConcreteRemote : RemoteControl
{
    private int CurrentStation { get; set; }

    public ConcreteRemote(TV tv) : base(tv)
    {
    }

    public void SetStation(int station)
    {
        CurrentStation = station;
        SetChannel(CurrentStation);
    }

    public void NextChannel()
    {
        SetStation(CurrentStation + 1);
    }

    public void PreviousChannel()
    {
        SetStation(CurrentStation - 1);
    }
}

Test

测试代码

csharp
var miRC = new ConcreteRemote(new MiTV());
miRC.On();
miRC.SetStation(10);
miRC.NextChannel();
miRC.Off();

var leRC = new ConcreteRemote(new LeTV());
leRC.On();
leRC.SetStation(24);
leRC.PreviousChannel();
leRC.Off();