Java设计模式之-桥接模式
什么是桥接模式?
桥接模式(Bridge Pattern)是一种结构型设计模式,其主要目标是将抽象与实现解耦,使得两者可以独立地变化。在桥接模式中,我们有一个抽象类和一个实现类,抽象类依赖于实现类。这样,如果我们想要改变实现或者抽象,我们可以独立地做到这一点。
主要解决什么问题?
桥接模式主要解决的是类的维度爆炸问题。如果一个类有多个独立变化的维度,那么不使用设计模式,我们可能需要为每一种可能的组合创建一个子类。这样会导致子类数量大幅增加,且难以管理和维护。桥接模式通过将这些维度分离,并使它们各自独立地变化,有效地解决了这个问题。
在什么时候我们需要使用桥接模式?
当你需要避免永久的绑定抽象类和实现类时,或者两个独立变化的类时,你应该使用桥接模式。此外,如果你希望在几个类之间共享实现,也应该使用桥接模式。
生活中的应用实例
想象一下你正在构建一个跨平台的图形用户界面框架。你有不同类型的元素,如按钮、复选框等,而且你希望它们在所有主要操作系统(Windows、Linux、macOS)上工作。
你可以创建一个大的类层次结构来覆盖所有可能的组合,如 WindowsButton、LinuxButton 等等,但这样做会导致类的数量爆炸,并且在添加新的操作系统或元素类型时,你需要修改所有类。桥接模式可以帮助你避免这个问题。
优点
抽象和实现的分离:这是桥接模式的主要优点,它能使抽象和实现独立地变化,增加或改变实现不会影响抽象类。
提高可扩展性:你可以独立地增加抽象和实现的类。
实现了细节对客户端的隐藏:你可以对客户隐藏实现的细节。
缺点
增加了系统的理解和设计难度:桥接模式将抽象和实现分离,这可能使理解和设计系统更加复杂。
需要正确识别出系统中两个独立变化的维度:识别出系统中的两个独立变化的维度需要对系统有深入的理解和分析。
使用场景
当一个类存在两个独立变化的维度,并且这两个维度都需要进行扩展时,我们可以使用桥接模式。
代码示例
// 实现类接口
interface Implementor {
void operationImpl();
}
// 具体实现类
class ConcreteImplementorA implements Implementor {
public void operationImpl() {
System.out.println("Concrete Implementor A");
}
}
class ConcreteImplementorB implements Implementor {
public void operationImpl() {
System.out.println("Concrete Implementor B");
}
}
// 抽象类
abstract class Abstraction {
protected Implementor implementor;
protected Abstraction(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
// 扩展抽象类
class RefinedAbstraction extends Abstraction {
protected RefinedAbstraction(Implementor implementor) {
super(implementor);
}
public void operation() {
implementor.operationImpl();
}
}
public class BridgePatternDemo{
public static void main(String[] args) {
Implementor implementorA = new ConcreteImplementorA();
Abstraction abstractionA = new RefinedAbstraction(implementorA);
abstractionA.operation();
Implementor implementorB = new ConcreteImplementorB();
Abstraction abstractionB = new RefinedAbstraction(implementorB);
abstractionB.operation();
}
}
在这个例子中,Abstraction 是抽象类,Implementor 是实现类接口。我们有两个具体的实现类 ConcreteImplementorA 和 ConcreteImplementorB,以及一个扩展抽象类 RefinedAbstraction。在 main 方法中,我们创建了两个 RefinedAbstraction 的实例,一个使用 ConcreteImplementorA,另一个使用 ConcreteImplementorB。当我们调用 operation 方法时,每个实例都会调用相应的 operationImpl 方法。