问题:
在面向对象的设计中,抽象是一个很重要的概念,所谓抽象就是忽略一类对象的特殊特性,提出一些共有的特性,暂时忽略一些细节,而对与此类对象的变化可以使用继承的手段在子类中完成,换言之,用继承来应对抽象的变化。在软件系统中,当抽象由于某种原因也容易变动,使得对象从两个维度或更多方向上发生改变。使用继承方案往往违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比继承方案更好的解决方法。定义:
桥接模式(Bridge Pattern),将抽象部分与它的实现部分分离,使的抽象和实现都可以独立地变化。意图:
Bridge模式,系统被分为抽象(Abstraction)和实现(Implemetor)两个相对独立的部分抽象部(这里所谓的“抽象”与“实现”的含义不是指子类继承抽象基类实现具体的方法,抽象是指需求的抽象,而实现是指通过对象组合实现用户的需求),这两个部分可以互相独立地进行修改。Implemetor(还可以扩展到更多变化方向)部分的抽象,以抽象类的形式组合到抽象(Abstraction)部分的抽象类中,在抽象部分的主实现对象RefinedAbstraction中隔离了对实现部分(Implemetor)变化对象的具体实现(ConcreteImplemetor)的依赖。参与者:•抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。 •修正抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。 •实现化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。实现化角色给出的底层操作,抽象化角色给出基于底层操作的更高一层的操作。•具体实现化(Concrete Implementor)角色:这个角色给出实现化角色接口的具体实现
UML:
实例说明:
诺基亚手机工厂
抽象的手机工厂要应对不同型号的手机(N8,N9的生产方式可能不一样)生产差异的变化,又要应对不同网络类型(GSM,CDMA生产方式可能不一样)的差异变化uml:
•使用继承模式:
•使用桥接模式:
代码:
/// <summary> /// 手机生产抽象角色 抽象接口 /// </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)中,违反开闭原则应用情景:当系统有多维角度分类时,而每一种分类又有非常强的变化,时使用桥接模式比较合适 转()