C#设计模式(10)——桥接模式
1.桥接模式介绍
桥接模式用于将抽象化和实现化解耦,使得两者可以独立变化。在面向对象中用通俗的话说明:一个类可以通过多角度来分类,每一种分类都可能变化,那么就把多角度分离出来让各个角度都能独立变化,降低各个角度间的耦合。这样说可能不太好理解,举一个画几何图形的例子:我们画的几何图形可以按照形状和颜色两个角度的进行分类,按形状分类,分为圆形、长方形、三角形,按照颜色分类分为蓝色图形、黄色图形和红色图形,而形状和颜色都是可以添加的,比如我们也可以添加五角星形状,颜色可以添加一个绿色。如果按继承来实现的话,如图1所示,我们需要的具体的子类就有9种(形状种类*颜色种类),如果我们添加一个五角星形状,则必须再添加蓝色五角星,黄色五角星和红色五角星三个具体子类,添加一种颜色也一样需要添加这个颜色的各种形状。当我们的形状和颜色的种类都很多时,就需要很多的具体子类,造成子类爆炸。
画图的例子只有两个角度的分类,当一个类有更多角度分类时,具体子类种类(分类1种类*分类2种类*分类3种类...)就更多了。这时我们可以用桥接模式优化,将形状和颜色通过继承生产的强耦合关系改成弱耦合的关联关系,这里采用了组合大于继承的思想。如下图,采用桥接模式时,如果我们想添加一个五角星,只需要添加一个形状类的子类五角星接即可,不需要再去添加各种颜色的具体五角星了,如果我们想要一个蓝色五角星就将五角星和蓝色进行组合来获取。这样设计降低了形状和颜色的耦合,减少了具体子类的种类。
桥接模式的角色
Abstraction:抽象化生成的类,如形状类;
Implementor:行为实现接口,抽象化后关注的其他的特性,如例子中颜色接口。注意:我们可以把颜色抽象化生成抽象类,把形状作为行为实现接口;
RefinedAbstraction:抽象类子类,如圆形,长方形等;
ConcreteImplementor:行为实现接口的实现类,如黄色,红色等;
画几何图形例子的代码实现
形状抽象类和三种子类的形状:
public abstract class Shape { //形状内部包含了另一个维度:color protected IColor color; public void SetColor(IColor color) { this.color = color; } //设置形状 public abstract void Draw(); } /// <summary> /// 圆形 /// </summary> public class Circle : Shape { public override void Draw() { color.Paint("圆形"); } } /// <summary> /// 长方形 /// </summary> public class Rectangle : Shape { public override void Draw() { color.Paint("长方形"); } } /// <summary> /// 三角形 /// </summary> public class Triangle : Shape { public override void Draw() { color.Paint("三角形"); } }
颜色接口和三种实现类:
/// <summary> /// 颜色接口 /// </summary> public interface IColor { void Paint(string shape); } /// <summary> /// 蓝色 /// </summary> public class Blue : IColor { public void Paint(string shape) { Console.WriteLine($"蓝色的{shape}"); } } /// <summary> /// 黄色 /// </summary> public class Yellow : IColor { public void Paint(string shape) { Console.WriteLine($"黄色的{shape}"); } } /// <summary> /// 红色 /// </summary> public class Red : IColor { public void Paint(string shape) { Console.WriteLine($"红色的{shape}"); } }
客户端调用代码:
class Program { static void Main(string[] args) { Shape circle = new Circle(); IColor blue = new Blue(); circle.SetColor(blue);//设置颜色 circle.Draw();//画图 Shape triangle = new Triangle(); triangle.SetColor(blue); triangle.Draw(); Console.ReadKey(); } }
程序运行结果
2.小结
上边例子的类图:
桥接模式的使用场景:
当系统实现有多个角度分类,每种分类都可能变化时使用。近几年提出的微服务概念采用了桥接模式的思想,通过各种服务的组合来实现一个大的系统。
桥接模式的优点:
1.实现抽象和具体的分离,降低了各个分类角度间的耦合;
2.扩展性好,解决了多角度分类使用继承可能出现的子类爆炸问题。
桥接模式的缺点:
桥接模式的引进需要通过聚合关联关系建立抽象层,增加了理解和设计系统的难度。