设计模式学习总结-桥接模式(Bridge Pattern)
问题:
在面向对象的设计中,抽象是一个很重要的概念,所谓抽象就是忽略一类对象的特殊特性,提出一些共有的特性,暂时忽略一些细节,而对与此类对象的变化可以使用继承的手段在子类中完成,换言之,用继承来应对抽象的变化。在软件系统中,当抽象由于某种原因也容易变动,使得对象从两个维度或更多方向上发生改变。使用继承方案往往违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比继承方案更好的解决方法。
定义:
桥接模式(Bridge Pattern),将抽象部分与它的实现部分分离,使的抽象和实现都可以独立地变化。
意图:
Bridge模式,系统被分为抽象(Abstraction)和实现(Implemetor)两个相对独立的部分抽象部(这里所谓的“抽象”与“实现”的含义不是指子类继承抽象基类实现具体的方法,抽象是指需求的抽象,而实现是指通过对象组合实现用户的需求),这两个部分可以互相独立地进行修改。Implemetor(还可以扩展到更多变化方向)部分的抽象,以抽象类的形式组合到抽象(Abstraction)部分的抽象类中,在抽象部分的主实现对象RefinedAbstraction中隔离了对实现部分(Implemetor)变化对象的具体实现(ConcreteImplemetor)的依赖。
参与者:
•抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。
•修正抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
•实现化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。实现化角色给出的底层操作,抽象化角色给出基于底层操作的更高一层的操作。
•具体实现化(Concrete Implementor)角色:这个角色给出实现化角色接口的具体实现
UML:
实例说明:
诺基亚手机工厂
抽象的手机工厂要应对不同型号的手机(N8,N9的生产方式可能不一样)生产差异的变化,又要应对不同网络类型(GSM,CDMA生产方式可能不一样)的差异变化
uml:
•使用继承模式:
•使用桥接模式:
代码:
/// 手机生产抽象角色 抽象接口
/// </summary>
public abstract class PhoneFactory
{
protected PhoneNetType phoneNetType;
public void SetNetType(PhoneNetType _phoneNetType)
{
phoneNetType = _phoneNetType;
}
public abstract void Create();
}
/// <summary>
/// 手机生产 抽象角色 RefinedAbstraction
/// </summary>
public class Factory_N8 : PhoneFactory
{
public override void Create()
{
phoneNetType.CreatePhone();
System.Console.WriteLine("我是N8");
}
}
/// <summary>
/// 手机生产 抽象角色 RefinedAbstraction
/// </summary>
public class Factory_N9 : PhoneFactory
{
public override void Create()
{
phoneNetType.CreatePhone();
System.Console.WriteLine("我是N9");
}
}
/// <summary>
/// 手机生产 Implementor
/// </summary>
public abstract class PhoneNetType
{
public abstract void CreatePhone();
}
/// <summary>
/// 手机生产 ConcreteImplementor
/// </summary>
public class Factory_Csm : PhoneNetType
{
public override void CreatePhone()
{
System.Console.WriteLine("我是一款GSM网络手机。");
}
}
/// <summary>
/// 手机生产 ConcreteImplementor
/// </summary>
public class Factory_Cdma : PhoneNetType
{
public override void CreatePhone()
{
System.Console.WriteLine("我是一款CDMA网络手机。");
}
}
/// <summary>
/// 客户端测试代码
/// </summary>
public void BridgeTest()
{
PhoneFactory pf = new Factory_N8();
pf.SetNetType(new Factory_Csm());
pf.Create();
}
优点:
•Bridge模式使用“合成/聚合复用原则”解耦了抽象和实现之间的高耦合关系,使得抽象和实现可以沿着各自的维度来变化(通过各自继承)。
•抽象化角色和具体化角色之间增加更多的灵活性,当有新的抽象或实现方式时,只需要继承一个抽象和继承一个实现即可。
•实现化角色的任何改变不影响客户端。
缺点:
•Bridge模式不能应对维度数量的变化,如果要重新抽象出另外一个维度类型,则需要修改抽象角色,将新的实现(Implemetor)组合进抽象(Abstraction)中,违反开闭原则
应用情景:
当系统有多维角度分类时,而每一种分类又有非常强的变化,时使用桥接模式比较合适