桥接模式的概念
桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与它的实现部分分离,使它们都可以独立地变化。这种模式又称为柄体(Handle and Body)模式或接口(Interface)模式。在软件系统中,当某个类型由于自身的逻辑而具有两个或多个维度的变化时,桥接模式可以应对这种“多维度的变化”,并利用面向对象的技术使该类型能够轻松地沿着多个方向进行变化,而又不引入额外的复杂度。
桥接模式的优缺点
优点:
- 分离抽象类及其实现部分:桥接模式使用对象间的关联关系解耦了抽象和现实之间固有的绑定关系,使得抽象和实现可以沿着各自的维度变化。
- 取代多层继承方案:多层继承方案违背了单一职责原则,复用性较差,且类的个数非常多。桥接模式可以解决这个问题。
- 提供系统的扩展性:在两个变化维度中任意扩展一个维度,不需要修改原有系统,符合开闭原则。
缺点:
- 增加系统的理解和设计难度:由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行编程。
- 使用范围有限:桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性。
桥接模式的应用场景
- 需要在抽象化和具体化之间增加更多的灵活性的场景。
- 一个类存在两个或多个独立变化的维度,而这两个或多个维度都需要独立进行扩展。
- 不希望使用继承,或因为多层继承导致系统类的个数剧增。
桥接模式的代码实现
在桥接模式中,通常包含以下几个角色:
- 抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。
- 修正抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
- 实现化(Implementor)角色:给出实现化角色的接口,但不给出具体的实现。
- 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
以下是一个简单的Java代码示例,用于展示桥接模式的基本结构:
// 实现化角色接口 | |
public interface Implementor { | |
void operationImpl(); | |
} | |
// 具体实现化角色A | |
public class ConcreteImplementorA implements Implementor { | |
@Override | |
public void operationImpl() { | |
System.out.println("ConcreteImplementorA operationImpl"); | |
} | |
} | |
// 具体实现化角色B | |
public class ConcreteImplementorB implements Implementor { | |
@Override | |
public void operationImpl() { | |
System.out.println("ConcreteImplementorB operationImpl"); | |
} | |
} | |
// 抽象化角色 | |
public abstract class Abstraction { | |
protected Implementor implementor; | |
public Abstraction(Implementor implementor) { | |
this.implementor = implementor; | |
} | |
public abstract void operation(); | |
} | |
// 修正抽象化角色 | |
public class RefinedAbstraction extends Abstraction { | |
public RefinedAbstraction(Implementor implementor) { | |
super(implementor); | |
} | |
@Override | |
public void operation() { | |
super.implementor.operationImpl(); | |
} | |
} | |
// 客户端代码 | |
public class Client { | |
public static void main(String[] args) { | |
Implementor implementorA = new ConcreteImplementorA(); | |
Abstraction abstraction = new RefinedAbstraction(implementorA); | |
abstraction.operation(); // 输出 "ConcreteImplementorA operationImpl" | |
Implementor implementorB = new ConcreteImplementorB(); | |
abstraction = new RefinedAbstraction(implementorB); | |
abstraction.operation(); // 输出 "ConcreteImplementorB operationImpl" | |
} | |
} |
这个示例展示了如何使用桥接模式将抽象部分和实现部分分离,并使它们能够独立地变化。