C++ 设计模式之桥接模式

news2024/12/27 13:31:31

【声明】本题目来源于卡码网(题目页面 (kamacoder.com))

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】


【简介】什么是桥接模式

        桥接模式(Bridge Pattern)是⼀种结构型设计模式,它的UML图很像⼀座桥,它通过将【抽象部分】与【实现部分】分离,使它们可以独⽴变化,从⽽达到降低系统耦合度的⽬的。桥接模式的主要⽬的是通过组合建⽴两个类之间的联系,⽽不是继承的⽅式。
        举个简单的例⼦,图形编辑器中,每⼀种图形都需要蓝⾊、红⾊、⻩⾊不同的颜⾊,如果不使⽤桥接模式,可能需要为每⼀种图形类型和每⼀种颜⾊都创建⼀个具体的⼦类,⽽使⽤桥接模式可以将图形和颜⾊两个维度分离,两个维度都可以独⽴进⾏变化和扩展,如果要新增其他颜⾊,只需添加新的 Color ⼦类,不影响图形类;反之亦然。


【基本结构】

桥接模式的基本结构分为以下⼏个⻆⾊:

  • 抽象Abstraction :⼀般是抽象类,定义抽象部分的接⼝,维护⼀个对【实现】的引⽤。
  • 修正抽象RefinedAbstaction :对抽象接⼝进⾏扩展,通常对抽象化的不同维度进⾏变化或定制。
  • 实现Implementor : 定义实现部分的接⼝,提供具体的实现。这个接⼝通常是抽象化接⼝的实现。
  • 具体实现ConcreteImplementor :实现实现化接⼝的具体类。这些类负责实现实现化接⼝定义的具体操作。

 

         再举个例⼦,遥控器就是抽象接⼝,它具有开关电视的功能,修正抽象就是遥控器的实例,对遥控器的功能进⾏实现和扩展,⽽电视就是实现接⼝,具体品牌的电视机是具体实现,遥控器中包含⼀个对电视接⼝的引⽤,通过这种⽅式,遥控器和电视的实现被分离,我们可以创建多个遥控器,每个遥控器控制⼀个品牌的电视机,它们之间独⽴操作,不受电视品牌的影响,可以独⽴变化。


【简易实现】

        下⾯是实现桥接模式的基本步骤:(以Java代码作以说明)

1. 创建实现接口

interface Implementation {
    void operationImpl();
}

2. 创建具体实现类:实际提供服务的对象

class ConcreteImplementationA implements Implementation {
    @Override
    public void operationImpl() {
        // 具体实现A
    }
}
class ConcreteImplementationB implements Implementation {
    @Override
    public void operationImpl() {
        // 具体实现B
    }
}

3. 创建抽象接⼝:包含⼀个对实现化接⼝的引⽤。

public abstract class Abstraction {
    protected IImplementor mImplementor;

    public Abstraction(IImplementor implementor) {
        this.mImplementor = implementor;
    } 
   
    public void operation() {
        this.mImplementor.operationImpl();
    }
}

4. 实现抽象接⼝,创建RefinedAbstaction 类

class RefinedAbstraction implements Abstraction {
    private Implementation implementation;

    public RefinedAbstraction(Implementation implementation) {
        this.implementation = implementation;
    }

    @Override
    public void operation() {
        // 委托给实现部分的具体类
        implementation.operationImpl();
    }
}

5. 客户端使⽤

// 客户端代码
public class Main {
    public static void main(String[] args) {
    // 创建具体实现化对象
    Implementation implementationA = new ConcreteImplementationA();
    Implementation implementationB = new ConcreteImplementationB();
    // 使⽤扩充抽象化对象,将实现化对象传递进去
    Abstraction abstractionA = new RefinedAbstraction(implementationA);
    Abstraction abstractionB = new RefinedAbstraction(implementationB);
    // 调⽤抽象化的操作
    abstractionA.operation();
    abstractionB.operation();
    }
}

【使用场景】

         桥接模式在⽇常开发中使⽤的并不是特别多,通常在以下情况下使⽤:

  • 当⼀个类存在两个独⽴变化的维度,⽽且这两个维度都需要进⾏扩展时,使⽤桥接模式可以使它们独⽴变化,减少耦合。
  • 不希望使⽤继承,或继承导致类爆炸性增⻓

        总体⽽⾔,桥接模式适⽤于那些有多个独⽴变化维度、需要灵活扩展的系统


【编码部分】

1. 题目描述

        小明家有一个万能遥控器,能够支持多个品牌的电视。每个电视可以执行开机、关机和切换频道的操作,请你使用桥接模式模拟这个操作。

2. 输入描述

        第一行是一个整数 N(1 <= N <= 100),表示后面有 N 行输入。接下来的 N 行,每行包含两个数字。第一个数字表示创建某个品牌的遥控和电视,第二个数字表示执行的操作。其中,0 表示创建 Sony 品牌的电视,1 表示创建 TCL 品牌的遥控和电视;2 表示开启电视、3表示关闭电视,4表示切换频道。        

3. 输出描述

        对于每个操作,输出相应的执行结果。

4. C++编码实例

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file BridgeMode.hpp
* @brief 桥接模式
* @autor 写代码的小恐龙er
* @date 2024/01/11
*/

#include <iostream>
#include <string>

using namespace std;

// 前置声明
// 实现化接口
class TV;
// ======== 第一个维度的扩充 ========

// 具体实现类1 -- Sony Tv
class SonyTv;
// 具体实现类2 -- TCL Tv
class TclTv;

// ----------------------------------

// 抽象化接口
class RemoteControl;
// ======== 第二个维度的扩充 ========

// 实现抽象化接口 -- 开机
class TurnOn;
// 实现抽象化接口 -- 关机
class TurnOff;
// 实现抽象化接口 -- 切换频道
class SwitchChannel;


// 实现化接口
class TV
{
    // 接口函数
public:
    virtual void TurnOnTV() = 0;
    virtual void TurnOffTV() = 0;
    virtual void SwitchTVChannel() = 0;
};

// 具体实现类1 -- Sony Tv
class SonyTv : public TV
{
 public:
 // 重载接口函数
    void TurnOnTV(){
        std::cout << "Sony TV is ON" << endl;
    }
    void TurnOffTV(){
        std::cout << "Sony TV is OFF" << endl;
    }
    void SwitchTVChannel(){
        std::cout << "Switching Sony TV channel" << endl;
    }
};

// 具体实现类2 -- TCL Tv
class TclTv : public TV
{
public:
 // 重载接口函数
    void TurnOnTV(){
        std::cout << "TCL TV is ON" << endl;
    }
    void TurnOffTV(){
        std::cout << "TCL TV is OFF" << endl;
    }
    void SwitchTVChannel(){
        std::cout << "Switching TCL TV channel" << endl;
    }
};


// 抽象化接口
class RemoteControl
{
// 抽象化接口类持有实现化接口类的实例
protected:
    TV *_tv;

public:
    // 重载构造函数
    RemoteControl(){}
    RemoteControl(TV *tv){
        this->_tv = tv;
    }
    
    // 提供抽象类接口函数
    virtual void OperationMode() = 0;
};

// 实现抽象化接口 -- 开机
class TurnOn : public RemoteControl
{
private:
    // 实现抽象接口类持有实现化接口类的实例
    TV *_tv;
    
public:
    // 重载构造函数 以便后续调用能传入抽象类
    TurnOn(TV *tv){
        this->_tv = tv;
    }
    
    // 重载抽象类接口函数
    void OperationMode() override {
        this->_tv->TurnOnTV();
    }
    
};
// 实现抽象化接口 -- 关机
class TurnOff : public RemoteControl
{
private:
    // 实现抽象接口类持有实现化接口类的实例
    TV *_tv;
    
public:
    // 重载构造函数 以便后续调用能传入抽象类
    TurnOff(TV *tv){
        this->_tv = tv;
    }
    
    // 重载抽象类接口函数
    void OperationMode() override {
        this->_tv->TurnOffTV();
    }
};

// 实现抽象化接口 -- 切换频道
class SwitchChannel : public RemoteControl
{
private:
    // 实现抽象接口类持有实现化接口类的实例
    TV *_tv;
    
public:
    // 重载构造函数 以便后续调用能传入抽象类
    SwitchChannel(TV *tv){
        this->_tv = tv;
    }
    
    // 重载抽象类接口函数
    void OperationMode() override {
        this->_tv->SwitchTVChannel();
    }    
    
};

int main()
{
   // 执行操作的数量
   int operationNum = 0;
   // 输入
   std::cin >> operationNum;
   // 创建实现化接口
   TV *tv = nullptr;
   RemoteControl *control = nullptr;
   // 遍历输入
   for(int i = 0; i < operationNum; i++)
   {
       // 电视机类型
       int tvType = -1;
       // 遥控器操作类型
       int controlType = -1;
       // 输入
       std:: cin >> tvType >> controlType;
       
       // 电视机类型
       if(!tvType){
           tv = new SonyTv();
       }
       else if(tvType == 1){
           tv = new TclTv();
       }
       else tv = nullptr;
       
       // 若输入指令错误则直接返回
       if(tv == nullptr) return 0;
       
       // 遥控器操作类型
       if(controlType == 2){
           control = new TurnOn(tv);
       }
       else if(controlType == 3){
           control = new TurnOff(tv);
       }
       else if(controlType == 4){
           control = new SwitchChannel(tv);
       }
       else control = nullptr;
       
       // 若输入指令错误则直接返回
       if(control == nullptr) return 0;
       
       // 执行操作
       control->OperationMode();
   }
    
    delete tv;
    tv = nullptr;
    delete control;
    control = nullptr;
    
    return 0;
}


......

To be continued.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1388909.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【技术分享】远程透传网关-单网口快速实现三菱 Q03UDV PLC程序远程上下载

准备工作 一台可联网操作的电脑一台单网口的远程透传网关及博达远程透传配置工具网线一条&#xff0c;用于实现网络连接和连接PLC一台三菱 FX5U PLC及其编程软件一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡&#xff0c;WIFI联网则将WIFI天线插入USB口&#xff09; …

在校大学生可以考哪些 ?(38个考证时间表)

这是整理的在校大学生可以考的&#xff0c;有的对报名条件没有要求&#xff0c;有的是高中以上学历&#xff0c;还有一些应届生可以报考的。可以在支付宝搜索【亿鸣证件照】或者微信搜索【随时照】制作这些考证要求的证件照哦 1、教师资格证 2、英语四六级 3、计算机二级 4、普…

adb wifi 远程调试 安卓手机 命令

使用adb wifi 模式调试需要满足以下前提条件&#xff1a; 手机 和 PC 需要在同一局域网下。手机需要开启开发者模式&#xff0c;然后打开 USB 调试模式。 具体操作步骤如下&#xff1a; 将安卓手机通过 USB 线连接到 PC。&#xff08;连接的时候&#xff0c;会弹出请求&#x…

2. goLand安装及外配置参数通用用法

目录 概述测试代码解决外配置参数结束 概述 选择版本安装 go 安装的版本 1.go安装及相关配置 goLand 对于 习惯 idea 系列使用的人&#xff0c;还是很友好的。 测试代码 package mainimport ("flag""fmt""os" )func main() {name : flag.St…

layabox_2d游戏A*寻路实践

使用工具 Red Blob Games 效果 项目地址 LayaAStar2D: Laya2.0引擎2D游戏使用AStar实践。

加速 Android Studio 依赖项下载

在某些网络环境中&#xff0c;访问互联网可能受到限制&#xff0c;在Android Studio中&#xff0c;项目构建时可能需要下载依赖项&#xff0c;如果网络受到限制&#xff0c;就无法下载或下载速度非常慢只有十几 kb/s &#xff0c;设置可以帮助解决下载问题。 进入设置页面找到…

【杂七杂八】GyP-DataLoader

前言&#xff1a; pytorch :2.0.0cuda 11.8Jupyter Notebook:7.0.6所以 PyG不需要安装依赖包&#xff0c;直接cuda/pip install ; Jupyter Notebook 有扩展管理器&#xff0c;不需要也装不了 很多教程里的扩展管理插件 &#x1f601; 1 基本数据结构 torch_geometric.data.Data…

Spring AOP 源码分析

【阅读前提】&#xff1a; 需了解AOP注解开发流程&#xff1a;链接 一、注解 EnableAspectJAutoProxy 在配置类中添加注解EnableAspectJAutoProxy&#xff0c;便开启了AOP&#xff08;面向切面编程&#xff09; 功能。此注解也是了解AOP源码的入口。 EnableAspectJAutoProxy…

蓝桥杯备赛 | 洛谷做题打卡day2

​ 蓝桥杯备赛 | 洛谷做题打卡day2 嵌套循环yyds&#xff01;&#xff01; 题目来源&#xff1a;洛谷P2670 [NOIP2015 普及组] 扫雷游戏 题目背景 NOIP2015 普及组 T2 题目描述 扫雷游戏是一款十分经典的单机小游戏。在 n n n 行 m m m 列的雷区中有一些格子含有地雷&am…

❤ Uniapp使用二 ( 日常使用篇)

❤ Uniapp使用二 ( 日常使用篇) 一、表单 1、基础表单验证 form <form submit"formSubmit" reset"formReset"> <view class"uni-form-item uni-column"><view class"title">请选择类型{{selectvalue}}</view&…

海思SD3403,SS928/926,hi3519dv500,hi3516dv500移植yolov7,yolov8(9)

上一节yolov8的训练已经完成了,现在要开始做模型的转换了,这里和yolov7方式相似,但是有一些差异,尤其是yolov7的不带NMS部分的输出顺序和yolov8的输出顺序与格式是有差异的。 首先还是要自己手动加入rpn_op,这里包含了filter,sort,nms部分。 我们一个一个看,首先filter.py…

深度学习基础知识整理

自动编码器 Auto-encoders是一种人工神经网络&#xff0c;用于学习未标记数据的有效编码。它由两个部分组成&#xff1a;编码器和解码器。编码器将输入数据转换为一种更紧凑的表示形式&#xff0c;而解码器则将该表示形式转换回原始数据。这种方法可以用于降维&#xff0c;去噪…

高级分布式系统-第15讲 分布式机器学习--分布式机器学习算法

高级分布式系统汇总&#xff1a;高级分布式系统目录汇总-CSDN博客 分布式机器学习算法 按照通信步调&#xff0c;大致可以分为同步算法和异步算法两大类。 同步算法下&#xff0c;通信过程中有一个显式的全局同步状态&#xff0c;称之为同步屏障。当工作节点运行到同步屏障 …

MySQL索引创建原则和失效问题

一.索引创建原则 数据量较大,且查询比较频繁的表常作为查询条件、分组、排序的字段字段内容区分度高内容较长,使用前缀索引尽量创建联合索引要控制索引的数量如果索引列不能存储NULL值,请在创建表示使用NOT NULL约束它 二.索引失效 违反最左前缀法则范围查询右边的列,不能使用…

可持续技术:2024 年技术趋势的绿色创新

随着我们步入2024年&#xff0c;对可持续技术解决方案的关注从未如此强烈。从可再生能源到环保小工具&#xff0c;科技行业正朝着更环保、更可持续的未来大步迈进。 在快速发展的技术领域&#xff0c;创新是推动我们走向可持续未来的动力。随着我们步入2024年&#xff0c;对可持…

基于Docker Compose单机实现多级缓存架构2024

文章目录 一、环境参考二、专栏简介三、扩展 一、环境参考 NameVersionDocker Desktop for Windows4.23.0Openjdk8MySQL8.2.0Redis7.2Canal1.1.7OpenResty1.21.4.3-3-jammy-amd64Lua-Caffeine- 二、专栏简介 多级缓存实现过程比较长&#xff0c;将拆分为多个文章分步讲述。如…

[我的rust付费栏目]rust跟我学(一)已上线

大家好&#xff0c;我是开源库get_local_info的作者带剑书生&#xff0c;get_local_info诞生半个月&#xff0c;现在已经获得500的下载量&#xff0c;并获社区日更前五名&#xff0c;后被西安城市开发者社区收录&#xff08;【我的Rust库】get_local_info 0.1.5发布_rust_科比布…

CMake 实战构建TcpServer项目 静态库/动态库

爱编程的大丙CMake&#xff1a; 20. 举例 - 下_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV14s4y1g7Zj?p20&spm_id_frompageDriver&vd_sourcea934d7fc6f47698a29dac90a922ba5a3 hehedalinux:~/Linux/LinuxServerCpp$ ls Buffer.cpp Log.h Buffe…

墙地砖外形检测的技术方案-图像分割

基础原理 由于对碗口进行缺口检测&#xff0c;因此只需要碗口的边界信息。得到陶瓷碗区域填充后的图像&#xff0c;对图像进行边缘检测。这是属于图像分割中的内容&#xff0c;在图像的边缘中&#xff0c;可以利用导数算子对数字图像求差分&#xff0c;将边缘提取出来。 案例…

shell脚本算术运算

算术运算符 注意&#xff1a; 不是单引号&#xff0c;是键盘左上角那个反单引号条件表达式要放在方括号之间&#xff0c;并且要有空格&#xff0c;例如:[ a a ab]是错误的&#xff0c;必须写成[ $a $b ]。cost_Minexpr $cost_time / 60 前后不能有空格&#xff0c;否则出…