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

【声明】本题目来源于卡码网(题目页面 (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.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

不是人才用不起,而是AI巡检更有性价比!

在许多行业中&#xff0c;如煤炭、电力、化工等&#xff0c;安全生产是至关重要的。这就需要通过巡检&#xff0c;对设备运行状态进行实时监测&#xff0c;及时发现并处理潜在的安全隐患&#xff0c;从而降低事故发生的概率。但是传统的巡检方式通常依赖于人工进行&#xff0c;…

Java项目:121SSM记账管理系统

博主主页&#xff1a;Java旅途 简介&#xff1a;分享计算机知识、学习路线、系统源码及教程 文末获取源码 一、项目介绍 记账管理系统基于SpringSpringMVCMybatis开发&#xff0c;系统主要功能如下&#xff1a; 收入项管理 支出项管理 收入方式管理 支出方式管理 添加收入…

申泰勇教练的独家人物化身系列即将登陆 The Sandbox

申泰勇&#xff08;Shin Tae-yong&#xff09;教练是足球界的传奇人物&#xff0c;他来到 The Sandbox&#xff0c;推出了自己的专属人物化身系列。作为前 K 联赛中场球员和印尼队取得历史性成就的幕后教练&#xff0c;他的传奇经历现在已经影响到了虚拟世界。 向过去、现在和未…

Linux第29步_安装“Notepad++”软件

STM32CubeProgrammer脚本文件的后缀为“.tsv”&#xff0c;ST公司官方也叫做FlashLayout。在烧写“TF-A固件”之前&#xff0c;我们需要用“Notepad”软件打开“后缀为.tsv”的脚本文件&#xff0c;根据需求决定哪些文件需要更新&#xff0c;设置好这个脚本文件。 在后期使用S…

AnyText多语言文字生成与编辑

AnyText图文融合 近年来&#xff0c;随着AIGC的爆火&#xff0c;图片生成技术得到飞速发展&#xff0c;当前AI生成的图片已达到真假难辨的高保真度。不过&#xff0c;当合成图片中出现文字内容时&#xff0c;仍能够使AI露出马脚&#xff0c;因为当前主流方法尚无法在图片中生成…

一个程序员“玩”出来的网站:每月成本仅 350 元,如今赚了 16.4 万元

很难想象&#xff1a;一个每月运行成本不到 50 美元&#xff08;约人民币 358 元&#xff09;的网站. 是如何做到收入 2.3 万美元&#xff08;约人民币 16.4 万元&#xff09;的&#xff1f; ** 如果你也对网站开发感兴趣&#xff1f; ** 首先&#xff0c;这个网站只有创始…

【动态规划】【滑动窗口】【C++算法】 629K 个逆序对数组

作者推荐 【矩阵快速幂】封装类及测试用例及样例 本文涉及知识点 动态规划 C算法&#xff1a;滑动窗口总结 LeetCode629: K 个逆序对数组 逆序对的定义如下&#xff1a;对于数组 nums 的第 i 个和第 j 个元素&#xff0c;如果满足 0 < i < j < nums.length 且 nu…

【架构】docker实现集群主从扩容【案例3/4】

实现集群主从扩容 当整个集群扛不住流量的情况时&#xff0c;需要给集群扩容增加设备&#xff0c;由3主3从&#xff0c;扩为4主4从。实现&#xff1a; 示意图如下&#xff1a; 第一步&#xff1a;新创建两个节点&#xff08;redis-node-7&#xff0c;端口6387和 redis-node…

「云渲染科普」3dmax vray动画渲染参数如何设置

动画渲染一直都是占用时间最多的地方&#xff0c;动画帧数通常 1 秒在 25 帧或者以上&#xff0c;电脑通常需要对每一帧的画面分批渲染&#xff0c;通常本地电脑由于配置上的限制&#xff0c;往往无法在短时间内快速的完成渲染任务。这时“云渲染”则成为了动画渲染的主要方案&…

USB Cable导致连接识别不良

2根USB线&#xff0c;连接USB2RS232芯片&#xff0c;有根线能够识别&#xff0c;另外一根不能识别。 好的线识别如下&#xff1a; 另外一根就不能识别

josef 约瑟抗干扰中间继电器 UEG/F-4H 四常开 导轨安装

系列型号 UEG/F-2H2D抗干扰中间继电器;UEG/F-1H1D抗干扰中间继电器; UEG/F-10H-L抗干扰中间继电器;UEG/F-10H-L2抗干扰中间继电器; UEG/F-10HS抗干扰中间继电器;UEG/F-2DPDT抗干扰中间继电器; UEG/F-4DPDT抗干扰中间继电器;UEG/F-8DPDT抗干扰中间继电器; UEG/F-2H抗干扰中间继…

(六)深入理解Bluez协议栈之“GATT Client Profile”

前言: 本章节我们继续介绍GATT Client Profile的实现,参考的程序是tools\btgatt-client.c,需要注意的一点,在./configure时,需要添加 --enable-test --enable-testing才会编译该c文件,编译完成后,生成的可执行程序为btgatt-client。本文主要以btgatt-client运行时可能会…

【Python数据可视化】matplotlib之绘制常用图形:折线图、柱状图(条形图)、饼图和直方图

文章传送门 Python 数据可视化matplotlib之绘制常用图形&#xff1a;折线图、柱状图&#xff08;条形图&#xff09;、饼图和直方图matplotlib之设置坐标&#xff1a;添加坐标轴名字、设置坐标范围、设置主次刻度、坐标轴文字旋转并标出坐标值matplotlib之增加图形内容&#x…

Angular系列教程之管道

文章目录 管道的基本概念使用内置管道创建自定义管道总结 在Angular中&#xff0c;管道&#xff08;Pipe&#xff09;是一个非常重要的概念。它们允许我们对数据进行转换、格式化和显示&#xff0c;并且可以轻松地在模板中使用。本篇文章将介绍Angular中的管道概念&#xff0c;…

golang文件相对路径问题

目录结构 2.具体代码&#xff1a; const dataFile "../data/data.json"_, fileName, _, _ : runtime.Caller(1)dataPath : path.Join(path.Dir(fileName), dataFile)fmt.Println(dataPath)// open filefile, err : os.Open(dataPath)if err ! nil {log.Fatalln(err…

AI扩展手写数字识别应用(二)

理解代码 输入处理 在新应用的代码部分&#xff0c;和我们在手写数字识别课程介绍的代码比起来&#xff0c;差别最大的地方就在于如何处理输入。在上个案例中&#xff0c;我们只需要简单地将正方形区域中的图像格式调整一下&#xff0c;即可用作MNIST模型的输入。而在本文的案…

【运维】安装双系统之后,如何删除主硬盘的Linux的引导,图文教程

前置条件&#xff1a;已经安装了windows10系统和Linux系统&#xff0c;而且windows10系统是C盘主要盘&#xff0c;Linux系统是安装在别的硬盘上&#xff0c;这个时候C盘主要盘里面的引导分区里是由Linux的引导的&#xff0c;所以打开电脑之后才能让你选是使用windows系统还是使…

一文了解Spring线程池(超详细+干货满满)

Spring默认线程池 simpleAsyncTaskExecutor Spring异步线程池的接口类是TaskExecutor &#xff0c;本质还是 java.util.concurrent.Executor&#xff0c;没有配置的情况下&#xff0c;默认使用的是 simpleAsyncTaskExecutor Component EnableAsync public class ScheduleTask…

josef约瑟 漏电继电器 LLJ-400F Φ100 分体式结构,导轨安装

LLJ-400F AC660V漏电继电器是一种检测线路触&#xff08;漏&#xff09;电&#xff0c;并发出一个机械开闭信号至控制电路装置。它可与各种规格的低压断路器或交流接触器组成组合式剩余电流动作保护器。在如今已实现了较为完善的农村低压电网分级&#xff08;二级或三级&#x…

Linux-->进程概念

文章目录 进程进程概念操作系统管理进程描述进程-PCB组织进程task_strcut 查看Linux下进程信息通过系统文件查看通过命令查看 通过系统调用获取进程标示符通过系统调用frok创建进程fork的使用进程状态运行阻塞挂起Linux下具体的进程状态 前台进程和后台进程kill僵尸进程孤儿进程…