Bridge 模式

  • ~12.14K 字
  1. 1. Bridge 模式
    1. 1.1. 一、基础介绍
    2. 1.2. 二、生活比喻:电视遥控器
    3. 1.3. 三、应用场景
    4. 1.4. 四、使用注意事项
      1. 1.4.1. 优点
      2. 1.4.2. 缺点
      3. 1.4.3. 使用建议
    5. 1.5. 五、Java 经典案例
      1. 1.5.1. 实现 1:形状与颜色(解决类爆炸)
      2. 1.5.2. 实现 2:跨平台窗口系统
    6. 1.6. 六、Python 经典案例
      1. 1.6.1. 实现 1:消息发送器(多通道)
      2. 1.6.2. 实现 2:支付方式与支付渠道
    7. 1.7. 七、参考资料与延伸阅读
      1. 1.7.1. 经典书籍
      2. 1.7.2. 在线资源
      3. 1.7.3. 相关设计模式
      4. 1.7.4. 最佳实践建议

Bridge 模式

一、基础介绍

Bridge(桥接)模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化。

Bridge 模式的核心思想是:使用组合代替继承,将抽象层次(功能)与实现层次(平台)分离,通过桥接连接两者

二、生活比喻:电视遥控器

想象一台电视和遥控器

传统方式(继承):每家电视厂商都要为每种型号的电视生产专门的遥控器。如果你想换遥控器样式,就得换电视;想换电视品牌,就得换遥控器。两者紧密绑定。

桥接方式(组合):制定统一的遥控器接口(Implementor),电视(Abstraction)通过接口控制。任何品牌的遥控器都能控制任何型号的电视,两者独立变化。

在这个比喻中:

  • Abstraction = 电视机(抽象部分,定义控制接口)
  • RefinedAbstraction = 具体型号的电视机
  • Implementor = 遥控器接口(实现部分)
  • ConcreteImplementor = 具体品牌的遥控器

三、应用场景

场景 说明 示例
类爆炸问题 继承导致子类数量爆炸 形状×颜色=大量子类
多维变化 系统有多个独立变化的维度 操作系统×窗口类型
平台独立 抽象与平台需要独立演进 跨平台UI组件
运行时切换 需要在运行时切换实现 可插拔的驱动程序

四、使用注意事项

优点

优点 说明
分离抽象与实现 两者可以独立变化
减少子类数量 避免类爆炸
运行时灵活 可以动态切换实现
符合开闭原则 新增抽象或实现无需修改现有代码

缺点

缺点 说明
增加复杂性 需要识别两个独立变化的维度
设计难度 正确分离抽象与实现需要经验
间接性:增加了系统的理解成本

使用建议

  • 系统有多维变化时使用
  • 想避免多层继承时使用
  • 需要在运行时切换实现时使用
  • 简单的单维变化使用继承即可

五、Java 经典案例

实现 1:形状与颜色(解决类爆炸)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
* 实现者接口:颜色
*/
interface Color {
String apply();
}

/**
* 具体实现者
*/
class RedColor implements Color {
public String apply() {
return "红色";
}
}

class BlueColor implements Color {
public String apply() {
return "蓝色";
}
}

class GreenColor implements Color {
public String apply() {
return "绿色";
}
}

/**
* 抽象类:形状
*/
abstract class Shape {
protected Color color;

public Shape(Color color) {
this.color = color;
}

abstract public String draw();
}

/**
* 扩展抽象:具体形状
*/
class Circle extends Shape {
private int radius;

public Circle(Color color, int radius) {
super(color);
this.radius = radius;
}

public String draw() {
return "画一个" + color.apply() + "的圆形,半径=" + radius;
}
}

class Rectangle extends Shape {
private int width;
private int height;

public Rectangle(Color color, int width, int height) {
super(color);
this.width = width;
this.height = height;
}

public String draw() {
return "画一个" + color.apply() + "的矩形,宽=" + width + ",高=" + height;
}
}

// 使用
public class BridgeDemo {
public static void main(String[] args) {
// 红色圆形
Shape redCircle = new Circle(new RedColor(), 10);
System.out.println(redCircle.draw());

// 蓝色矩形
Shape blueRect = new Rectangle(new BlueColor(), 20, 30);
System.out.println(blueRect.draw());

// 绿色圆形
Shape greenCircle = new Circle(new GreenColor(), 15);
System.out.println(greenCircle.draw());
}
}

实现 2:跨平台窗口系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
* 实现者接口:窗口实现
*/
interface WindowImpl {
void devDrawText(String text);
void devDrawRect(int x, int y, int w, int h);
void devDrawLine(int x1, int y1, int x2, int y2);
}

/**
* 具体实现:Linux 窗口
*/
class LinuxWindowImpl implements WindowImpl {
public void devDrawText(String text) {
System.out.println("[Linux] Drawing text: " + text);
}
public void devDrawRect(int x, int y, int w, int h) {
System.out.println("[Linux] Drawing rect: " + x + "," + y + "," + w + "," + h);
}
public void devDrawLine(int x1, int y1, int x2, int y2) {
System.out.println("[Linux] Drawing line: " + x1 + "," + y1 + " to " + x2 + "," + y2);
}
}

/**
* 具体实现:Windows 窗口
*/
class WindowsWindowImpl implements WindowImpl {
public void devDrawText(String text) {
System.out.println("[Windows] Drawing text: " + text);
}
public void devDrawRect(int x, int y, int w, int h) {
System.out.println("[Windows] Drawing rect: " + x + "," + y + "," + w + "," + h);
}
public void devDrawLine(int x1, int y1, int x2, int y2) {
System.out.println("[Windows] Drawing line: " + x1 + "," + y1 + " to " + x2 + "," + y2);
}
}

/**
* 抽象类:窗口
*/
abstract class Window {
protected WindowImpl windowImpl;

public Window(WindowImpl windowImpl) {
this.windowImpl = windowImpl;
}

abstract public void draw();
abstract public void drawText(String text);
}

/**
* 扩展抽象:图标窗口
*/
class IconWindow extends Window {
public IconWindow(WindowImpl windowImpl) {
super(windowImpl);
}

public void draw() {
windowImpl.devDrawRect(0, 0, 16, 16);
windowImpl.devDrawText("Icon");
}

public void drawText(String text) {
windowImpl.devDrawText(text);
}
}

/**
* 扩展抽象:应用程序窗口
*/
class ApplicationWindow extends Window {
public ApplicationWindow(WindowImpl windowImpl) {
super(windowImpl);
}

public void draw() {
windowImpl.devDrawRect(0, 0, 800, 600);
windowImpl.devDrawText("Application Window");
windowImpl.devDrawLine(0, 0, 800, 600);
}

public void drawText(String text) {
windowImpl.devDrawText(text);
}
}

// 使用
public class CrossPlatformDemo {
public static void main(String[] args) {
String os = System.getProperty("os.name").toLowerCase();
WindowImpl impl = os.contains("win") ? new WindowsWindowImpl() : new LinuxWindowImpl();

Window icon = new IconWindow(impl);
icon.draw();

Window app = new ApplicationWindow(impl);
app.draw();
}
}

六、Python 经典案例

实现 1:消息发送器(多通道)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from abc import ABC, abstractmethod
from typing import Protocol


class MessageSender(Protocol):
"""实现者接口:消息发送器"""

def send(self, message: str, recipient: str) -> None:
...


class EmailSender:
"""具体实现:邮件发送"""

def send(self, message: str, recipient: str) -> None:
print(f"发送邮件到 {recipient}: {message}")


class SMSSender:
"""具体实现:短信发送"""

def send(self, message: str, recipient: str) -> None:
print(f"发送短信到 {recipient}: {message}")


class PushNotificationSender:
"""具体实现:推送通知"""

def send(self, message: str, recipient: str) -> None:
print(f"推送通知到 {recipient}: {message}")


class NotificationSystem:
"""抽象类:通知系统"""

def __init__(self, sender: MessageSender):
self.sender = sender

def notify(self, message: str, recipient: str) -> None:
"""发送通知的模板方法"""
self.sender.send(message, recipient)


class AlertSystem(NotificationSystem):
"""扩展抽象:告警系统"""

def send_alert(self, level: str, message: str, recipient: str) -> None:
formatted_msg = f"[{level} 告警] {message}"
self.notify(formatted_msg, recipient)


class MarketingSystem(NotificationSystem):
"""扩展抽象:营销系统"""

def send_promotion(self, product: str, discount: int, recipient: str) -> None:
formatted_msg = f"{product} 特惠!立减 {discount} 元!"
self.notify(formatted_msg, recipient)


# 使用
def main():
# 使用邮件发送告警
email_alert = AlertSystem(EmailSender())
email_alert.send_alert("紧急", "服务器CPU使用率过高", "admin@example.com")

# 使用短信发送营销信息
sms_marketing = MarketingSystem(SMSSender())
sms_marketing.send_promotion("Python课程", 100, "13800138000")

# 使用推送发送通知
push_alert = AlertSystem(PushNotificationSender())
push_alert.send_alert("警告", "检测到异常登录", "user123")


if __name__ == "__main__":
main()

实现 2:支付方式与支付渠道

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from abc import ABC, abstractmethod
from typing import Protocol


class PaymentMethod(Protocol):
"""实现者接口:支付渠道"""

def process(self, amount: float) -> bool:
...

def get_balance(self) -> float:
...


class CreditCard:
"""信用卡支付"""

def __init__(self, limit: float):
self._limit = limit
self._used = 0

def process(self, amount: float) -> bool:
if self._limit - self._used >= amount:
self._used += amount
print(f"信用卡支付 {amount} 元成功")
return True
print(f"信用卡额度不足,支付失败")
return False

def get_balance(self) -> float:
return self._limit - self._used


class WeChatPay:
"""微信支付"""

def __init__(self, balance: float):
self._balance = balance

def process(self, amount: float) -> bool:
if self._balance >= amount:
self._balance -= amount
print(f"微信支付 {amount} 元成功")
return True
print(f"微信余额不足,支付失败")
return False

def get_balance(self) -> float:
return self._balance


class Alipay:
"""支付宝"""

def __init__(self, balance: float):
self._balance = balance

def process(self, amount: float) -> bool:
if self._balance >= amount:
self._balance -= amount
print(f"支付宝支付 {amount} 元成功")
return True
print(f"支付宝余额不足,支付失败")
return False

def get_balance(self) -> float:
return self._balance


class Payment(ABC):
"""抽象类:支付"""

def __init__(self, method: PaymentMethod):
self.method = method

@abstractmethod
def make_payment(self, amount: float) -> bool:
pass


class OnlineShopping(Payment):
"""扩展抽象:网购支付"""

def make_payment(self, amount: float) -> bool:
print(f"=== 网购订单支付 ===")
print(f"订单金额: {amount} 元")
print(f"支付方式余额: {self.method.get_balance()} 元")
success = self.method.process(amount)
if success:
print("订单支付成功,等待发货")
else:
print("订单支付失败,请更换支付方式")
return success


class UtilityBill(Payment):
"""扩展抽象:生活缴费"""

def make_payment(self, amount: float) -> bool:
print(f"=== 生活缴费 ===")
print(f"缴费金额: {amount} 元")
success = self.method.process(amount)
if success:
print("缴费成功")
else:
print("缴费失败")
return success


# 使用
def main():
# 创建支付方式
credit_card = CreditCard(10000)
wechat = WeChatPay(500)
alipay = Alipay(200)

# 网购使用信用卡
shopping1 = OnlineShopping(credit_card)
shopping1.make_payment(2999)

# 网购使用微信
shopping2 = OnlineShopping(wechat)
shopping2.make_payment(199)

# 缴费使用支付宝
bill = UtilityBill(alipay)
bill.make_payment(150)


if __name__ == "__main__":
main()

七、参考资料与延伸阅读

经典书籍

  • 《设计模式:可复用面向对象软件的基础》- GoF
  • 《Head First 设计模式》- 桥接模式章节

在线资源

相关设计模式

  • Adapter(适配器):Adapter 适配已有接口,Bridge 分离抽象与实现
  • Abstract Factory(抽象工厂):可以与 Bridge 结合创建对象
  • Composite(组合):组合可以和 Bridge 一起使用
  • Strategy(策略):Strategy 专注算法,Bridge 专注结构分离

最佳实践建议

  1. 正确识别两个独立变化的维度
  2. 优先使用组合而非继承
  3. 抽象类持有实现者接口的引用
  4. 扩展抽象类可以添加新功能
打赏
打赏提示信息