设计模式之桥接模式

设计模式之桥接模式

什么是桥接设计模式?

桥接设计模式属于结构设计模式类别。 这种模式侧重于抽象概念的局限性。 在Java上下文中,我们使用继承来开发抽象概念。 有几个实现偏差支持实现继承。 但是,这将实现永久绑定到抽象上,从而限制了灵活性。 在某些情况下,您想独立地修改或扩展抽象以及实现。 桥接模式通过将抽象与其实现分离,将有助于解决该限制。

这种模式很好地说明了“优先考虑组成而不是继承”的概念

GOF定义的桥梁设计模式,

“将抽象与其实现分离开来,以便两者可以独立变化。”

什么是抽象?

如果我们想到Java语言的要点,则可以通过接口或抽象类来定义抽象。 这是定义抽象概念的非常狭窄的方法。 当认为是面向对象的概念时,抽象只是对更复杂细节的表示或概括。 抽象涵盖了整个事物的具体实现的细节。

通常,当抽象需要多个实现时,继承就是一种机制,用于满足该需求。 但是,某些方案要求独立添加或修改抽象以及实现,而不会给系统带来任何错误。

现实生活中的例子

假设汽车和遥控器场景。 汽车是这种情况的抽象。 丰田、本田和奥迪将成为汽车抽象的实现。 每辆汽车将具有一套遥控器。 如果远程控制是抽象远程启动器,则远程门锁/开和远程报警将作为远程控制的实现。 宝马这样的汽车实现中有一个新的补充。 它还应具有遥控器的3种实现方式。 因此,抽象和实现可以根据需求而变化。

桥接模式如何工作?

通常,在这种模式下,抽象类代表抽象。 该抽象维护一个单独的层次结构。 单独的层次结构维护抽象类的实现。 同样,模式允许类(抽象)及其作用(实现)随需要而变化。 植入包括一个抽象点和该层次结构下的几个实现标准。

桥接模式的结构

让我们使用抽象和具体的实现策略来阐明这一点。 假设您有两个系统,每个系统中都有抽象类和具体类。 系统X由“摘要A”组成,而具体实现则由“具体A”组成。 然后,系统Y由“摘要B”组成,其具体实现为“混凝土B”。 摘要A通过“ Has-A”关系与摘要B连接。 摘要A在其内部维护摘要B的实例。 这种“ Has-A”关系在两个系统之间架起了一座桥梁。 因此,模式包含两层抽象。 因此,该结构被称为桥接模式结构。

桥接模式解决的问题

在应用程序中,我们应该首先确定候选组件以开发一个抽象并作为实现。 抽象和实现分为两个层次结构,并独立维护。

桥接模式的标准技术说明

图2代表了桥梁设计模式的UML图。 它描述了两组抽象,它们独立变化。

桥接设计模式类图

桥梁设计模式的组成部分

  • Abstraction:这是桥接模式的核心组件之一,它包括对实现者的引用。
  • Refined Abstraction:这扩展了抽象并向实现者隐藏了更精细的元素。就是说,这不会影响实现者,以及这些实现,也不依赖于Implementor接口中的任何具体实现者。
  • Implementor:这是下级实施的接口。 这不需要直接与抽象有关。 它仅与has-a关系连接。
  • ConcreteImplementor:该组件通过定义实现来实现实现者接口。 实施细节对客户端隐藏。

实现桥接模式步骤

  1. 确定应独立变化的内容那就是您必须基于正交维度派生和分析类。 它们可能像前端/后端,域/基础架构以及接口/平台类层次结构
  2. 通过分析候选类别的不同功能来识别“实现者”界面
  3. 将一个类类别标识为“抽象”,并构建抽象类,并在抽象类中包含“实现者”的实例
  4. 然后扩展抽象类以生成不同的实现,以满足您的不同需求
  5. 构建客户端程序以满足您的需求
  6. 您可以根据需要为“抽象”和“执行器”添加更多具体的类,并扩展系统

代码示例

让我们举一个简单的例子来阐明这种模式。 假设一位数字艺术家需要创建具有不同颜色的形状。 他正在开发一个程序来实现这个目标。 最初,几乎没有其他选择。 但是,根据客户的要求,将有不同类型的形状和颜色可以适应以产生最佳效果。 因此,艺术家将来必须在“形状”类别中添加不同的形状,并在“颜色”类别中添加多种颜色。

在继续之前,让我们看看没有桥接模式的情况。

没有桥接模式

您将必须为具有困难命名模式的每种形状创建冗长而复杂的子类。

使用桥接模式

两个类层次结构将在两个类层次结构之间提供更大的灵活性。

让我们将此场景放到Java编程中。

该计划的组成部分

  • AbstractShape:表示一组具体的形状实现的抽象类/接口
  • RefinedShapeCircle:Circle是“ Shape”抽象的一种扩展
  • RefinedShapeTriangle:三角形是“ Shape”抽象的另一个示例
  • ColorImplementor:这是“颜色”类别的抽象,也是“形状”类别的实现的一部分。
  • ConcreteColorRed:“颜色”抽象的红色扩展
  • ConcreteColorGreen:“颜色”抽象的绿色扩展

Java代码示例

ColorImplementor.java

1
2
3
public interface ColorImplementor {
void applyColor();
}

AbstractShape.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public abstract class AbstractShape {

/**
* 创建实现者实例(组成)
*/
protected ColorImplementor color;

/**
* 以实现者作为输入参数的构造函数
* @param color
*/
public AbstractShape(ColorImplementor color) {
this.color = color;
}

/**
* 与将颜色填充到对象有关的抽象方法
*/
abstract void applyShapeColor();
}

RefinedShapeCircle.java

1
2
3
4
5
6
7
8
9
10
11
public class RefinedShapeCircle extends AbstractShape {
public RefinedShapeCircle(ColorImplementor color) {
super(color);
}

@Override
void applyShapeColor() {
System.out.println("Circle color applying...");
color.applyColor();
}
}

RefinedShapeTriangle.java

1
2
3
4
5
6
7
8
9
10
11
public class RefinedShapeTriangle extends AbstractShape {
public RefinedShapeTriangle(ColorImplementor color) {
super(color);
}

@Override
void applyShapeColor() {
System.out.print("Triangle color applying...");
color.applyColor();
}
}

ConcreteColorRed.java

1
2
3
4
5
6
public class ConcreteColorRed implements ColorImplementor {
@Override
public void applyColor() {
System.out.println("Applying Red....");
}
}

ConcreteColorGreen.java

1
2
3
4
5
6
public class ConcreteColorGreen implements ColorImplementor {
@Override
public void applyColor() {
System.out.println("Apply Green...");
}
}

ShapeColorTester.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ShapeColorTester {
public static void main(String[] args) {
// 创建Triangle实例并应用红色
System.out.println("Apply Red Color to the Triangle");
AbstractShape triangle = new RefinedShapeTriangle(new ConcreteColorRed());
triangle.applyShapeColor();

// 创建Triangle实例并应用绿色
System.out.println("Appying Green Color to the Triangle");
AbstractShape triagleGreen = new RefinedShapeTriangle(new ConcreteColorGreen());
triagleGreen.applyShapeColor();

// 创建Circle实例并应用红色
System.out.println("Appying Red Color to the Circle");
AbstractShape circleRed = new RefinedShapeCircle(new ConcreteColorRed());
circleRed.applyShapeColor();

// 创建Circle实例并应用绿色
System.out.println("Applying Green Color to the Circle");
AbstractShape circleGreen = new RefinedShapeCircle(new ConcreteColorGreen());
circleGreen.applyShapeColor();
}
}

输出结果:

1
2
3
4
5
6
7
8
9
10
11
Apply Red Color to the Triangle
Triangle color applying...Applying Red....
Appying Green Color to the Triangle
Triangle color applying...Apply Green...
Appying Red Color to the Circle
Circle color applying...
Applying Red....
Applying Green Color to the Circle
Circle color applying...
Apply Green...

何时使用桥接模式

  • 当需要取消抽象和实现之间的永久绑定或紧密耦合时。 在这种情况下,实现可以在运行时选择或切换
  • 需要通过子类分别扩展抽象和复合实现时。
  • 什么时候扩展实现中的更改不应影响客户端
  • 当系统中有几类类别的分层传播时

桥接设计模式的优势

  • 桥接模式允许两个抽象系统和实现者系统之间的独立变化
  • 它避免了客户端代码绑定到某个实现
  • 抽象和实现可以清楚地分开,便于将来扩展
  • 为跨平台开发提供了很好的解决方案
  • 非常适合在初始开发周期中使用存根进行测试

桥接设计模式的缺点

  • 如果可扩展组件的数量增加,此模式可能会导致复杂性
  • 消息不清晰可能导致性能问题

桥接器和适配器模式之间的区别

适配器用于消除已定义的系统与现有的两个系统之间的不兼容性,而桥接模式则用于在开发系统之前解决所有困难