设计模式中的桥梁模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化。桥梁模式的核心思想是通过组合而不是继承来实现不同维度的变化。
通俗地说,桥梁模式就像是一座桥,将两个不同的维度连接在一起。其中,一个维度是抽象部分(Abstraction),它定义了高层业务逻辑,并包含对实现部分的引用;另一个维度是实现部分(Implementation),它定义了底层实现的接口。
通过桥梁模式,我们可以在两个维度上独立地变化和扩展,而不会相互影响。这种解耦的设计使得系统更加灵活,易于维护和扩展。
下面是一个简单的示例代码来说明桥梁模式的应用:
// 实现部分接口
interface DrawingAPI {
void drawCircle(double x, double y, double radius);
}
// 具体的实现部分
class DrawingAPI1 implements DrawingAPI {
@Override
public void drawCircle(double x, double y, double radius) {
System.out.printf("API1.drawCircle at (%.2f, %.2f) with radius %.2f%n", x, y, radius);
}
}
// 具体的实现部分
class DrawingAPI2 implements DrawingAPI {
@Override
public void drawCircle(double x, double y, double radius) {
System.out.printf("API2.drawCircle at (%.2f, %.2f) with radius %.2f%n", x, y, radius);
}
}
// 抽象部分
abstract class Shape {
protected DrawingAPI drawingAPI;
protected Shape(DrawingAPI drawingAPI) {
this.drawingAPI = drawingAPI;
}
public abstract void draw();
}
// 具体的抽象部分
class CircleShape extends Shape {
private double x, y, radius;
public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {
super(drawingAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
@Override
public void draw() {
drawingAPI.drawCircle(x, y, radius);
}
}
public class BridgePatternExample {
public static void main(String[] args) {
Shape redCircle = new CircleShape(100, 100, 10, new DrawingAPI1());
Shape greenCircle = new CircleShape(200, 200, 20, new DrawingAPI2());
redCircle.draw();
greenCircle.draw();
}
}
在上述示例中,我们使用桥梁模式实现了一个简单的图形绘制系统。DrawingAPI接口定义了绘制图形的方法,有两个具体的实现类DrawingAPI1和DrawingAPI2。Shape是抽象部分的基类,它包含了对实现部分的引用,并定义了抽象的绘制方法draw()。CircleShape继承了Shape,并通过构造函数将实现部分的对象传递进去。最后,在main方法中创建了两个具体的图形对象,并调用它们的draw()方法来绘制图形。
桥梁模式的缺点包括:
总的来说,桥梁模式适用于存在多个独立变化维度的情况,或者需要在运行时切换不同实现的情况。它可以帮助我们实现更灵活、可扩展和可复用的系统设计。
假设有一个小镇上有两座相距很远的桥,分别是一座木桥和一座石桥。这两座桥分别代表了抽象部分和实现部分。每天早上,人们都要从小镇的一侧过桥去另一侧工作。
某天,小镇的镇长决定要修建一座新的桥,以便提供更多的通行便利性。为了实现这个目标,他决定使用桥梁模式。
镇长找来一个桥梁设计师,设计师告诉镇长,他可以设计一座新桥的抽象部分,即桥的结构和功能,不管是木桥还是石桥都可以。设计师还告诉镇长,他可以与两个工程师合作,一个擅长建造木桥,另一个擅长建造石桥。这两个工程师代表了实现部分。
设计师设计了一个抽象的桥模型,包含了通行的功能。然后,他与木桥工程师和石桥工程师一起合作,让他们根据设计制造出具体的桥。木桥工程师根据抽象模型建造了一座木桥,石桥工程师根据同样的抽象模型建造了一座石桥。
完成后,镇长和设计师非常高兴。现在,无论是木桥还是石桥,都可以作为新桥的实现部分。人们可以根据需要选择在哪座桥上通行,而不受具体桥的类型影响。
这个故事中的小镇和桥就是一个典型的应用场景。小镇代表了整个系统,而抽象部分是桥的结构和功能,实现部分则是具体的木桥和石桥。设计师就是桥梁模式的核心,他将抽象部分和实现部分分离,并协调它们的工作。通过桥梁模式,小镇的系统变得更加灵活和可扩展,可以根据需要选择不同的实现部分。
代码示例:
// 实现部分接口
interface Bridge {
void cross();
}
// 具体的实现部分
class WoodenBridge implements Bridge {
@Override
public void cross() {
System.out.println("Crossing the wooden bridge.");
}
}
// 具体的实现部分
class StoneBridge implements Bridge {
@Override
public void cross() {
System.out.println("Crossing the stone bridge.");
}
}
// 抽象部分
abstract class Town {
protected Bridge bridge;
protected Town(Bridge bridge) {
this.bridge = bridge;
}
public abstract void visit();
}
// 具体的抽象部分
class MorningTown extends Town {
public MorningTown(Bridge bridge) {
super(bridge);
}
@Override
public void visit() {
System.out.println("Visiting the town in the morning.");
bridge.cross();
}
}
// 具体的抽象部分
class EveningTown extends Town {
public EveningTown(Bridge bridge) {
super(bridge);
}
@Override
public void visit() {
System.out.println("Visiting the town in the evening.");
bridge.cross();
}
}
public class BridgePatternExample {
public static void main(String[] args) {
Bridge woodenBridge = new WoodenBridge();
Bridge stoneBridge = new StoneBridge();
Town morningTown = new MorningTown(woodenBridge);
Town eveningTown = new EveningTown(stoneBridge);
morningTown.visit();
eveningTown.visit();
}
}
在上述示例代码中,我们使用桥梁模式实现了一个简单的小镇和桥的系统。Bridge接口定义了桥的通行方法,有两个具体的实现类WoodenBridge和StoneBridge,分别表示木桥和石桥。Town是抽象部分的基类,它包含了对桥实现部分的引用,并定义了抽象的访问方法visit()。MorningTown和EveningTown继承了Town,并通过构造函数将实现部分的对象传递进去。最后,在main方法中创建了具体的小镇和桥对象,并调用它们的visit()方法来模拟访问小镇。