设计模式(八)—— 桥接模式
模式简介
将抽象部分与它的实现相分离,使它们都可以独立地变化。
桥接模式是一种结构型模式,又称柄体模式(Handle and Body)或接口模式(Interface)。
想象下面这幅图,由英文字母组成,每个字母可以有不同的颜色。
在控制台中输出以上内容,想想我们该怎样进行设计?
- 方案一:为每个字母提供不同颜色的版本
- 方案二:根据字母和颜色进行组合
显然方案一不太合适,我们无法为每一个字母定义所有的颜色。对于这种拥有两个维度的系统,方案二中类的数量更少,且扩展起来更方便。方案二即是桥接模式,将字母与颜色的实现相分离,对Letter类的操作都是由IColor接口实现的,我们将Letter和IColor之间的关系称为桥接。
结构说明
角色说明
- Abstraction
抽象类,包括一个Implementor类型的对象成员。
- RefinedAbstraction
扩充抽象子类,实现其中的抽象方法。
- Implementor
接口,包括一个定义基本操作的方法。
- ConcreteImplementor
实现Implementor接口。
示例分析
介绍完桥接模式的基本结构,回到第一节中的示例中:
首先定义IColor接口以及Letter抽象类:
interface IColor
{
void Paint(string letter);
}
abstract class Letter
{
protected IColor color;
public void SetColor(IColor color)
{
this.color = color;
}
public abstract void Write();
}
定义具体颜色类,实现IColor接口
class Red : IColor
{
public void Paint(string letter)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(letter);
}
}
class Blue : IColor
{
public void Paint(string letter)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.Write(letter);
}
}
class Black : IColor
{
public void Paint(string letter)
{
Console.ForegroundColor = ConsoleColor.Black;
Console.Write(letter);
}
}
定义抽象类Letter的子类,这里我们只定义需要的字母类。
class B : Letter
{
public override void Write()
{
color.Paint("B");
}
}
class D : Letter
{
public override void Write()
{
color.Paint("D");
}
}
class E : Letter
{
public override void Write()
{
color.Paint("E");
}
}
class G : Letter
{
public override void Write()
{
color.Paint("G");
}
}
class I : Letter
{
public override void Write()
{
color.Paint("I");
}
}
class R : Letter
{
public override void Write()
{
color.Paint("R");
}
}
客户端调用:
static void Main(string[] args)
{
Console.BackgroundColor = ConsoleColor.White;
B B = new B();
B.SetColor(new Black());
B.Write();
R R = new R();
R.SetColor(new Black());
R.Write();
I I = new I();
I.SetColor(new Black());
I.Write();
D D = new D();
D.SetColor(new Red());
D.Write();
G G = new G();
G.SetColor(new Black());
G.Write();
E E = new E();
E.SetColor(new Blue());
E.Write();
Console.ReadLine();
}
输出结果:
适用场景
-
一个类存在两个独立变化的维度,且两个维度都需要进行扩展。
- 如果一个系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系,通过桥接模式可以使它们在抽象层建立一个关联关系。
-
对一个抽象的实现部分进行修改不会影响到客户端代码。
优缺点
优点:
- 分离抽象接口及实现部分
- 类的复用性较好,严格遵守单一职责原则
- 提高了系统的可扩展性,两个维度中任意一个扩展,不影响原有系统
缺点:
- 增加了系统的设计难度。
- 适用范围具有一定的局限性,仅适用于系统中两个独立变化的维度。
桥接模式与适配器模式的区别
从结构上看,桥接模式和对象适配器模式有些相似,二者的不同主要在于两个模式应用于系统设计的不同阶段。桥接模式引用于系统设计初期阶段,对于存在两个独立变化维度的类可以使用桥接模式,使它们分别进行变化;而适配器模式主要用于系统完成之后,发现新的扩展于原有类无法协同工作时,可以采用适配器模式。但也有在设计初期考虑适配器模式的情况,主要是因为涉及大量第三方接口,无法修改源码的情况。