桥接模式
在面向对象的编程中,我们经常会使用继承,但事实上,很多情况用继承会带来麻烦,因为对象的继承关系是在编译时就定义好了,所以无法再运行时改变从父类继承的实现,子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。
因此,我们应该尽量使用合成/聚合,尽量不要使用类的继承。聚合表示一种弱的“拥有”关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。有限使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并被不太可能增长为不可控制的庞然大物。
在众多设计模式中,桥接模式是对合成/聚合的典型应用,假如实现系统可能有多个角度分类,每一种分类都有可能发生变化,那么就把这多种角度分离出来,让他们独立变化,减少它们之间的耦合。
例如,手机既有多个品牌,又有多种软件,就可以使用桥接模式实现,首先实现多种软件类:
abstract class HandsetSoft
{
public abstract void Run();
}
class HandsetGame : HandsetSoft
{
public override void Run()
{
Console.WriteLine("Run Handset Game.");
}
}
class HandsetAddressList : HandsetSoft
{
public override void Run()
{
Console.WriteLine("Run Handset Address List.");
}
}
下面实现多个手机品牌,在品牌类中使用聚合,引入不同的手机软件类:
abstract class HandsetBrand
{
protected HandsetSoft soft;
//设置当前需要使用的软件
public void SetHandsetSoft(HandsetSoft soft)
{
this.soft = soft;
}
abstract public void Run();
}
class HandsetABrand : HandsetBrand
{
public override void Run()
{
Console.WriteLine("HandsetA Run:");
soft.Run();
}
}
class HandsetBBrand : HandsetBrand
{
public override void Run()
{
Console.WriteLine("HandsetB Run:");
soft.Run();
}
}
客户端调用代码如下:
HandsetABrand brandA = new HandsetABrand();
brandA.SetHandsetSoft(new HandsetGame());
brandA.Run();
HandsetBBrand brandB = new HandsetBBrand();
brandB.SetHandsetSoft(new HandsetAddressList());
brandB.Run();
运行结果如下:
HandsetA Run:
Run Handset Game.
HandsetB Run:
Run Handset Address List.
在仅使用继承时,结构图如下,如果需要增加一个软件或一个手机品牌,都至少需要增加两个类,桥接模式巧妙地使用聚合关系替代了类的继承,这样,无论增加手机软件或是手机品牌,都只需要增加一个类既可。

浙公网安备 33010602011771号