C++结构型设计模式之桥接模式

devtools/2024/11/26 17:05:46/

桥接模式的意图和动机

桥接模式的意图是将抽象部分与它的实现部分分离,使它们可以独立地变化。这意味着你可以独立地修改或扩展抽象部分和实现部分,而不会相互影响。桥接模式的主要动机是通过这种分离来增强系统的灵活性和可扩展性。

桥接模式适用于解决什么问题

桥接模式适用于以下场景:

  1. 多维度变化:当一个系统需要在多个维度上进行扩展时,桥接模式可以避免类爆炸问题。例如,一个图形绘制系统中,图形可以是圆形、矩形等,而颜色可以是红色、蓝色等。如果为每种图形和颜色的组合创建一个类,将会导致类的数量急剧增加。

  2. 抽象与实现的分离:当需要分离抽象和实现,使得它们可以独立变化时,桥接模式是一个合适的选择。

  3. 避免永久绑定:当需要在运行时动态地切换实现时,桥接模式允许抽象和实现可以独立变化,从而避免永久绑定。

桥接模式的适用场合

桥接模式特别适用于以下场合:

  1. 系统需要在多个独立维度上扩展:例如,图形和颜色可以独立变化。
  2. 需要在运行时切换实现:例如,用户可以根据需要选择不同的图形库或颜色方案。
  3. 避免类爆炸:通过分离抽象和实现,避免创建大量的子类。

桥接模式的结构和参与角色

桥接模式的结构包括以下几个核心角色:

  1. Abstraction(抽象类):定义抽象部分的接口,并维护一个指向 Implementor 类型对象的引用。
  2. RefinedAbstraction(扩充抽象类):扩充由 Abstraction 定义的接口。
  3. Implementor(实现类接口):定义实现部分的接口,这个接口不必与 Abstraction 的接口完全一致。通常情况下,Implementor 接口只提供基本操作,而 Abstraction 定义了基于这些基本操作的更高层次的操作。
  4. ConcreteImplementor(具体实现类):实现 Implementor 接口并定义具体实现。

桥接模式的UML类图

+-----------------+          +-----------------+
|  Abstraction    |          |  Implementor    |
|-----------------|          |-----------------|
| + operation()   |<---------| + operationImp()|
+-----------------+          +-----------------+|                               ||                               |v                               v
+-----------------+          +-----------------+
| RefinedAbstraction |      | ConcreteImplementor|
|-----------------|          |-----------------|
| + operation()   |          | + operationImp()|
+-----------------+          +-----------------+

解释

  • Abstraction:定义抽象部分的接口,并维护一个指向 Implementor 的引用。
  • RefinedAbstraction:扩展 Abstraction 的接口,提供更丰富的操作。
  • Implementor:定义实现部分的接口。
  • ConcreteImplementor:实现 Implementor 接口,提供具体的实现。

通过这种结构,桥接模式允许抽象和实现可以独立变化,从而增强了系统的灵活性和可扩展性。

C++示例代码:

场景1:多维度变化(如图形和颜色)

在图形绘制系统中,图形可以是圆形、矩形等,颜色可以是红色、蓝色等。通过桥接模式,我们可以独立地扩展图形和颜色。

#include <iostream>// Implementor: 颜色接口
class Color {
public:virtual void applyColor() = 0;
};// ConcreteImplementor: 红色
class RedColor : public Color {
public:void applyColor() override {std::cout << "Applying red color" << std::endl;}
};// ConcreteImplementor: 蓝色
class BlueColor : public Color {
public:void applyColor() override {std::cout << "Applying blue color" << std::endl;}
};// Abstraction: 抽象图形
class Shape {
protected:Color* color;public:Shape(Color* c) : color(c) {}virtual void draw() = 0;
};// RefinedAbstraction: 圆形
class Circle : public Shape {
public:Circle(Color* c) : Shape(c) {}void draw() override {std::cout << "Drawing Circle. ";color->applyColor();}
};// RefinedAbstraction: 矩形
class Rectangle : public Shape {
public:Rectangle(Color* c) : Shape(c) {}void draw() override {std::cout << "Drawing Rectangle. ";color->applyColor();}
};int main() {// 创建颜色Color* red = new RedColor();Color* blue = new BlueColor();// 创建图形并应用颜色Shape* redCircle = new Circle(red);Shape* blueRectangle = new Rectangle(blue);// 绘制图形redCircle->draw();blueRectangle->draw();// 清理资源delete red;delete blue;delete redCircle;delete blueRectangle;return 0;
}

场景2:需要在运行时切换实现

假设我们有一个消息发送系统,消息可以通过短信或电子邮件发送。我们可以通过桥接模式在运行时切换发送方式。

#include <iostream>// Implementor: 消息发送接口
class MessageSender {
public:virtual void sendMessage(const std::string& message) = 0;
};// ConcreteImplementor: 短信发送
class SMSSender : public MessageSender {
public:void sendMessage(const std::string& message) override {std::cout << "Sending SMS: " << message << std::endl;}
};// ConcreteImplementor: 电子邮件发送
class EmailSender : public MessageSender {
public:void sendMessage(const std::string& message) override {std::cout << "Sending Email: " << message << std::endl;}
};// Abstraction: 消息
class Message {
protected:MessageSender* sender;public:Message(MessageSender* s) : sender(s) {}virtual void send(const std::string& message) = 0;
};// RefinedAbstraction: 普通消息
class TextMessage : public Message {
public:TextMessage(MessageSender* s) : Message(s) {}void send(const std::string& message) override {sender->sendMessage(message);}
};int main() {// 创建发送方式MessageSender* smsSender = new SMSSender();MessageSender* emailSender = new EmailSender();// 创建消息并选择发送方式Message* smsMessage = new TextMessage(smsSender);Message* emailMessage = new TextMessage(emailSender);// 发送消息smsMessage->send("Hello via SMS");emailMessage->send("Hello via Email");// 清理资源delete smsSender;delete emailSender;delete smsMessage;delete emailMessage;return 0;
}

场景3:避免类爆炸

假设我们有一个设备控制系统,设备可以是电视或空调,控制方式可以是遥控器或手机App。通过桥接模式,我们可以避免为每种设备和控制方式的组合创建大量的子类。

#include <iostream>// Implementor: 设备控制接口
class DeviceControl {
public:virtual void turnOn() = 0;virtual void turnOff() = 0;
};// ConcreteImplementor: 电视控制
class TVControl : public DeviceControl {
public:void turnOn() override {std::cout << "Turning on TV" << std::endl;}void turnOff() override {std::cout << "Turning off TV" << std::endl;}
};// ConcreteImplementor: 空调控制
class ACControl : public DeviceControl {
public:void turnOn() override {std::cout << "Turning on Air Conditioner" << std::endl;}void turnOff() override {std::cout << "Turning off Air Conditioner" << std::endl;}
};// Abstraction: 控制器
class Controller {
protected:DeviceControl* device;public:Controller(DeviceControl* d) : device(d) {}virtual void on() = 0;virtual void off() = 0;
};// RefinedAbstraction: 遥控器
class RemoteController : public Controller {
public:RemoteController(DeviceControl* d) : Controller(d) {}void on() override {std::cout << "Using Remote to turn on: ";device->turnOn();}void off() override {std::cout << "Using Remote to turn off: ";device->turnOff();}
};// RefinedAbstraction: 手机App
class AppController : public Controller {
public:AppController(DeviceControl* d) : Controller(d) {}void on() override {std::cout << "Using App to turn on: ";device->turnOn();}void off() override {std::cout << "Using App to turn off: ";device->turnOff();}
};int main() {// 创建设备DeviceControl* tv = new TVControl();DeviceControl* ac = new ACControl();// 创建控制器并选择设备Controller* remoteControlTV = new RemoteController(tv);Controller* appControlAC = new AppController(ac);// 使用遥控器控制电视remoteControlTV->on();remoteControlTV->off();// 使用手机App控制空调appControlAC->on();appControlAC->off();// 清理资源delete tv;delete ac;delete remoteControlTV;delete appControlAC;return 0;
}

代码说明

  1. DeviceControl:设备控制接口,定义了 turnOn 和 turnOff 方法。
  2. TVControl 和 ACControl:具体的设备实现类,分别实现电视和空调的开关操作。
  3. Controller:控制器抽象类,包含一个 DeviceControl 对象,并定义了 on 和 off 方法。
  4. RemoteController 和 AppController:具体的控制器实现类,分别实现遥控器和手机App的控制逻辑。
  5. main 函数:演示如何使用桥接模式来避免类爆炸问题,通过组合不同的设备和控制器来实现灵活的控制。

通过这种方式,我们可以灵活地组合不同的设备和控制器,而不需要为每种组合创建大量的子类。

 


http://www.ppmy.cn/devtools/137169.html

相关文章

ES实用面试题

一、es是什么&#xff0c;为什么要用它&#xff1f; ES通常是Elasticsearch的简称&#xff0c;它是一个基于Lucene构建的开源搜索引擎。Elasticsearch以其分布式、高扩展性和实时数据分析能力而闻名&#xff0c;广泛用于全文搜索、日志分析、实时监控等多种场景。 基本特点&am…

泷羽sec-linux

基础之linux 声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团…

大数据和云计算在 WMS 中的应用

【大家好&#xff0c;我是唐Sun&#xff0c;唐Sun的唐&#xff0c;唐Sun的Sun。】 在当今数字化时代&#xff0c;大数据和云计算技术正以前所未有的速度改变着各个行业的运作模式&#xff0c;仓储管理也不例外。仓库管理系统&#xff08;WMS&#xff09;作为仓储管理的核心工具…

【Excel】拆分多个sheet,为单一表格

Private Sub 分拆工作表() Application.ScreenUpdating True 让屏幕显示操作过程&#xff0c; Dim sht As Worksheet Dim MyBook As Workbook Set MyBook ActiveWorkbook For Each sht In MyBook.Sheets If sht.Visible True Then 隐藏的sheet跳过&#xff0c;否则会报1004无…

LeetCode—704. 二分查找(简单)

仅供个人学习使用 题目描述&#xff1a; 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 示例 1: 输入: nums [-1,0,3…

《硬件架构的艺术》笔记(五):低功耗设计

介绍 能量以热量形式消耗&#xff0c;温度升高芯片失效率也会增加&#xff0c;增加散热片或风扇会增加整体重量和成本&#xff0c;在SoC级别对功耗进行控制就可以减少甚至可能消除掉这些开支&#xff0c;产品也更小更便宜更可靠。本章描述了减少动态功耗和静态功耗的各种技术。…

一场开源视角的AI会议即将在南京举办

一场开源视角的AI会议&#xff0c;将于2024年11月30日在南京举办。 此次活动&#xff0c;知名开源导师-庄表伟老师将为大家介绍自己搭建的AI框架&#xff0c;同时被誉为2024年度的“开源之星”、[开源之道]主创适兕老师也将亲临南京为大家分享AI话题。 与此同时&#xff0c;您还…

uni-app 界面TabBar中间大图标设置的两种方法

一、前言 最近写基于uni-app 写app项目的时候&#xff0c;底部导航栏 中间有一个固定的大图标&#xff0c;并且没有激活状态。这里记录下实现方案。效果如下&#xff08;党组织这个图标&#xff09;&#xff1a; 方法一&#xff1a;midButton的使用 官方文档&#xff1a;ta…