Spiga

模式开发之旅(11):桥接模式

2010-07-17 21:39:53

桥接模式,也叫作桥梁模式,英文是 Bridge Design Pattern。这个模式可以说是 23 种设计模式中最难理解的模式之一了。

当然,这其中“最纯正”的理解方式,当属 GoF 的《设计模式》一书中对桥接模式的定义。毕竟,这 23 种经典的设计模式,最初就是由这本书总结出来的。在 GoF 的《设计模式》一书中,桥接模式是这么定义的:“Decouple an abstraction from its implementation so that the two can vary independently。”翻译成中文就是:“将抽象和实现解耦,让它们可以独立变化。

关于桥接模式,很多书籍、资料中,还有另外一种理解方式:“一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。”通过组合关系来替代继承关系,避免继承层次的指数级爆炸。这种理解方式非常类似于“组合优于继承”设计原则。

桥接模式的应用举例

比如一款手机可以安装不同的应用,而手机又有多种不同的品牌。如果将手机按品牌分类,其结构图如下:

按软件分类实现结构图

由于实现的方式有多种,桥接模式的核心意图就是把这些实现独立出来,让它们各自地变化。这就使得每种实现的变化不会影响其他实现,从而达到应对变化的目的。

代码实现:

//手机软件
abstract class HandsetSoft
{
    public abstract void Run();
}

//手机游戏
class HandsetGame : HandsetSoft
{
    public override void Run()
    {
        Console.WriteLine("运行手机游戏");
    }
}

//手机通讯录
class HandsetAddressList : HandsetSoft
{
    public override void Run()
    {
        Console.WriteLine("运行手机通讯录");
    }
}

//手机品牌
abstract class HandsetBrand
{
    protected HandsetSoft soft;

    //设置手机软件
    public void SetHandsetSoft(HandsetSoft soft)    //品牌需要关注软件,所以可以机器中安装软件,以备运行
    {
        this.soft = soft;
    }

    public abstract void Run();
}

//手机品牌N
class HandsetBrandN : HandsetBrand
{
    public override void Run()
    {
        soft.Run();
    }
}

//手机品牌M
class HandsetBrandM : HandsetBrand
{
    public override void Run()
    {
        soft.Run();
    }
}

//客户端调用代码
static void Main(string[] args)
{
    HandsetBrand ab;
    ab = new HandsetBrandN();

    ab.SetHandsetSoft(new HandsetGame());
    ab.Run();

    ab.SetHandsetSoft(new HandsetAddressList());
    ab.Run();

    ab = new HandsetBrandM();

    ab.SetHandsetSoft(new HandsetGame());
    ab.Run();

    ab.SetHandsetSoft(new HandsetAddressList());
    ab.Run();

    Console.Read();
}

这时假如我们需要增加一个功能,比如MP3音乐播放器,那么只增加这个类就可以了。不会影响其他任何类,类的个数也增加也只有一个。


//手机MP3播放
class HandsetMP3 : HandsetSoft
{
    public override void Run()
    {
        Console.WriteLine("运行手机MP3播放");
    }
}

如果是要增加S品牌,也只需要增加一个品牌子类就可以了。个数也是一个,不会影响其他类的改动。

//手机品牌S
class HandsetBrandS : HandsetBrand
{
    public override void Run()
    {
        soft.Run();
    }
}