前言
桥接模式是一种设计模式,它将抽象与实现分离,使它们可以独立变化。这种模式涉及到一个接口作为桥梁,使实体类的功能独立于接口实现类。这两种类型的类可以结构化改变而互不影响。
桥接模式的主要目的是通过将实现和抽象分离,使两者可以独立地变化。这种类型的设计模式属于结构型模式,它通过提供抽象和实现之间的桥接结构来实现这一点。
例如,一个电视遥控器,它的基本功能(开/关,音量控制等)是抽象的,而这些功能可以通过不同的实现方式(不同品牌的电视机)来实现。如果没有桥接模式,每个品牌的电视机都需要一个专门的遥控器。但有了桥接模式,就可以有一个通用的遥控器,通过桥接模式来控制不同品牌的电视机。
桥接(Bridge)模式包含以下主要角色:
- 抽象化(Abstraction)角色 :定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化(Refined Abstraction)角色 :是抽象化角色的子类,实现父类中的业务方法, 并通过组合关系调用实现化角色中的业务方法。
- 实现化(Implementor)角色 :定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化(Concrete Implementor)角色 :给出实现化角色接口的具体实现。
代码案例
在如下案例中,演示了使用桥接模式实现宠物店中,动物与颜色的组合,如果使用普通方式来写这个案例,我们可能需要写 m(种类) × n(颜色) 个类,而使用了桥接模式,我们只需要写m(种类) + n(颜色)个类,然后用他们来组合成不同的需求
Animal接口
实现创建第一个动物的接口
public interface IAnimal
{
void animal(string colour);
}
狗
实现类狗
public class Dog:IAnimal
{
public void animal(string colour)
{
Console.WriteLine("这只狗的颜色是:"+colour);
}
}
猫
实现类猫,如果后续需要更多的种类,只需要添加实现类
public class Cat:IAnimal
{
public void animal(string colour)
{
Console.WriteLine("这只猫的颜色是:"+colour);
}
}
颜色选择器
将动物的种类与颜色进行组合就是在这个类中实现,在颜色选择器中,声明了一个animal,然后设置了一个构造函数,传入一个animal类进来,并且写了一个抽象方法,用来打印动物。
public abstract class ColourSelect
{
protected IAnimal Animal;
protected ColourSelect(IAnimal animal)
{
Animal = animal;
}
public abstract void outAnimal(string colour);
}
白色
白色继承颜色选择器,将构造函数的参数传递给父类,并且重写了outAnimal方法,在里面调用了animal,其实就是我们上面一开始写的,输出动物+颜色
public class black : ColourSelect
{
public black(IAnimal animal) : base(animal)
{
}
public override void outAnimal(string colour)
{
Animal.animal(colour);
}
}
黑色
同上
public class white : ColourSelect
{
public white(IAnimal animal) : base(animal)
{
}
public override void outAnimal(string colour)
{
Animal.animal(colour);
}
}
测试结果
new一个继承颜色选择器的黑色类,传入一个cat类,因此black.outAnimal即是调用了cat类的animal方法,并且携带一个参数黑色,因此通过Console.WriteLine("这只猫的颜色是:"+colour);打印这只猫的颜色是:黑色,下面的白狗例子同上。
桥接模式优点
-
提高系统可扩展性:桥接模式通过抽象层与实现层的分离,使得两个变化维度可以独立扩展。这意味着我们可以在不修改现有代码的情况下,轻松地添加新的抽象或实现。
-
减少系统复杂度:通过引入抽象层,可以将系统的复杂性分解为更小的部分。这使得系统更易于理解和维护。
-
符合开闭原则:桥接模式允许在不修改现有代码的情况下扩展系统。这符合开闭原则,即软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
-
可复用性:实现层可以被多个抽象层复用,从而减少了代码的重复。
-
解耦:桥接模式通过将抽象与实现解耦,使得系统更加灵活,易于应对变化。
-
易于测试:由于抽象层与实现层的分离,我们可以更容易地为系统编写单元测试。
使用场景
除了上面举例中的场景外,桥接模式还适用于以下情况:
-
图形界面库:在图形用户界面(GUI)库中,窗口、按钮、文本框等控件可能具有多种外观和风格。使用桥接模式,我们可以将控件的抽象(如按钮的行为)与其具体实现(如按钮的绘制方式)分离,从而实现灵活的外观定制。
-
跨平台软件开发:当需要在不同操作系统或平台上运行软件时,可以使用桥接模式来隔离平台相关的代码。这样,我们可以在不修改核心功能代码的情况下,为不同平台提供特定的实现。
-
产品族类问题:对于一组具有相同抽象接口的产品族类,如果需要在不改变产品族类的情况下增加新的产品,那么可以使用桥接模式来实现。
-
插件式架构:在插件式架构中,插件的接口是固定的,但插件的实现可能因需求而异。桥接模式可以帮助我们实现这种架构,使得插件的接口与实现可以独立变化。
-
需要多层继承的场景:在某些情况下,使用多层继承可能会导致类层次结构过于复杂,且难以维护。此时,可以使用桥接模式来替代多层继承,通过组合而非继承的方式来实现系统的功能。