C#设计模式--桥接模式

思考并回答以下问题:

桥接模式介绍

桥接模式用于将抽象化和实现化解耦,使得两者可以独立变化。在面向对象中用通俗的话说明:一个类可以通过多角度来分类,每一种分类都可能变化,那么就把多角度分离出来让各个角度都能独立变化,降低各个角度间的耦合。这样说可能不太好理解,举一个画几何图形的例子:我们画的几何图形可以按照形状和颜色两个角度的进行分类,按形状分类,分为圆形、长方形、三角形,按照颜色分类分为蓝色图形、黄色图形和红色图形,而形状和颜色都是可以添加的,比如我们也可以添加五角星形状,颜色可以添加一个绿色。如果按继承来实现的话,如图1所示,我们需要的具体的子类就有9种(形状种类*颜色种类),如果我们添加一个五角星形状,则必须再添加蓝色五角星,黄色五角星和红色五角星三个具体子类,添加一种颜色也一样需要添加这个颜色的各种形状。当我们的形状和颜色的种类都很多时,就需要很多的具体子类,造成子类爆炸。

画图的例子只有两个角度的分类,当一个类有更多角度分类时,具体子类种类(分类1种类*分类2种类*分类3种类…)就更多了。这时我们可以用桥接模式优化,将形状和颜色通过继承生产的强耦合关系改成弱耦合的关联关系,这里采用了组合大于继承的思想。如下图,采用桥接模式时,如果我们想添加一个五角星,只需要添加一个形状类的子类五角星接即可,不需要再去添加各种颜色的具体五角星了,如果我们想要一个蓝色五角星就将五角星和蓝色进行组合来获取。这样设计降低了形状和颜色的耦合,减少了具体子类的种类。

桥接模式的角色

  • Abstraction:抽象化生成的类,如形状类;
  • Implementor:行为实现接口,抽象化后关注的其他的特性,如例子中颜色接口。注意:我们可以把颜色抽象化生成抽象类,把形状作为行为实现接口;
  • RefinedAbstraction:抽象类子类,如圆形,长方形等;
  • ConcreteImplementor:行为实现接口的实现类,如黄色,红色等;

画几何图形例子的代码实现

形状抽象类和三种子类的形状:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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("三角形");
}
}

颜色接口和三种实现类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/// <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}");
}
}

客户端调用代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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();
}
}

程序运行结果

小结

上边例子的类图:

桥接模式的使用场景

当系统实现有多个角度分类,每种分类都可能变化时使用。近几年提出的微服务概念采用了桥接模式的思想,通过各种服务的组合来实现一个大的系统。

桥接模式的优点

  • 1.实现抽象和具体的分离,降低了各个分类角度间的耦合;
  • 2.扩展性好,解决了多角度分类使用继承可能出现的子类爆炸问题。

桥接模式的缺点

桥接模式的引进需要通过聚合关联关系建立抽象层,增加了理解和设计系统的难度。

0%