桥接模式
概述
将抽象部分与它的实现部分分离,使它们都可以独立地发生变化,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。(符合组合优于继承的设计原则)
一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。”通过组合关系来替代继承关系,避免继承层次的指数级爆炸。
“抽象”,指的并非“抽象类”或“接口”,而是被抽象出来的一套“类库”,它只包含骨架代码,真正的业务逻辑需要委派给定义中的“实现”来完成。而定义中的“实现”,也并非“接口的实现类”,而是一套独立的“类库”。“抽象”和“实现”独立开发,通过对象之间的组合关系,组装在一起。
结构图
代码实现
抽象化
/// <summary> /// 抽象化 /// </summary> public class Abstraction { protected Implementor1 implementor1; protected Implementor2 implementor2; public void SetImplementor(Implementor1 implementor1, Implementor2 implementor2) { this.implementor1 = implementor1; this.implementor2 = implementor2; } public virtual void Operation() { implementor1.Operation1(); implementor2.Operation2(); } }
/// <summary> /// 抽象化扩展1(骨架) /// </summary> public class RefinedAbstraction1 : Abstraction { public override void Operation() { Console.WriteLine("扩展抽象化(RefinedAbstraction1)角色被访问"); implementor1.Operation1(); implementor2.Operation2(); } }
/// <summary> /// 抽象化扩展2(骨架) /// </summary> public class RefinedAbstraction2 : Abstraction { public override void Operation() { Console.WriteLine("扩展抽象化(RefinedAbstraction2)角色被访问"); implementor2.Operation2(); implementor1.Operation1(); } }
实现化
/// <summary> /// 实现化1 /// </summary> public abstract class Implementor1 { public abstract void Operation1(); } public class ConcreteImplementor1A : Implementor1 { public override void Operation1() { Console.WriteLine("Implementor1具体实现A的方法执行"); } } public class ConcreteImplementor1B : Implementor1 { public override void Operation1() { Console.WriteLine("Implementor1具体实现B的方法执行"); } }
/// <summary> /// 实现化2 /// </summary> public abstract class Implementor2 { public abstract void Operation2(); } public class ConcreteImplementor2A : Implementor2 { public override void Operation2() { Console.WriteLine("Implementor2具体实现A的方法执行"); } } public class ConcreteImplementor2B : Implementor2 { public override void Operation2() { Console.WriteLine("Implementor2具体实现B的方法执行"); } }
客户端
static void Main(string[] args) { Abstraction ab1 = new RefinedAbstraction1(); ab1.SetImplementor(new ConcreteImplementor1B(),new ConcreteImplementor2A()); ab1.Operation(); Abstraction ab2 = new RefinedAbstraction2(); ab2.SetImplementor(new ConcreteImplementor1B(), new ConcreteImplementor2A()); ab2.Operation(); Console.Read(); }
运行结果
优势
组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
符合开闭原则,组合复用(CARP)原则,其实现细节对客户透明
使用场景
在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
享元模式 、单例、缓存、对象池的异同
享元模式有点类似于单例模式的变种,多例,但是在设计意图上是不同的。享元模式是为了对象复用,节省内存,而多例模式是为了限制对象的个数
缓存是为了提高访问效率,而享元是为了复用
池化技术的重复使用主要是为了节省时间,每一个对象并不会被多处使用,而是被一个使用者独占,使用完成后放回到池中,而享元模式所有使用者都是共享的,主要目的是节省空间
缺陷
由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。