C++设计模式之桥模式

news2025/1/11 6:03:12

桥模式也是设计模式中单一组件模式的一种。什么是单一组件模式呢?

单一组件模式:

  • 在软件组件设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化而变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。 
  • 典型的单一组件模式有装饰模式和桥模式。

如下代码是我们没有学习过桥模式写出的代码,下面代码通过功能分解的方法将一个复杂功能伪代码实现。下面代码挺简单,我就不仔细说明了。

class Messager {
public:
	virtual void Login(string username, string password) = 0;
	virtual void SendMessage(string message) = 0;
	virtual void SendPicture(Image image) = 0;

	virtual void PlaySound() = 0;
	virtual void DrawShape() = 0;
	virtual void WriteText() = 0;
	virtual void Connect() = 0;

	virtual ~Messager(){}
};

// 平台实现
class PCMessagerbase :public Messager { //PC平台
public:
	virtual void PlaySound() {
		//**********
	}
	virtual void PlaySound() {
		//**********
	}
	virtual void WriteText() {
		//**********
	}
	virtual void Connect() {
		//**********
	}
};
class MobileMessagerbase :public Messager { //移动平台
public:
	virtual void PlaySound() {
		//**********
	}
	virtual void PlaySound() {
		//**********
	}
	virtual void WriteText() {
		//**********
	}
	virtual void Connect() {
		//**********
	}
};
// 业务抽象
class PCMessageLite : public PCMessagerbase {
public:
	virtual void Login(string username, string password) {
		PCMessagerbase::Connect();
		//**********
	}
	virtual void SendMassage(string message) {
		PCMessagerbase::WriteText();
		//*********
	}
	virtual void SendPicture(Image image) {
		PCMessagerbase::DrawShape();
		//*********
	}
};
class PCMessagePerfect : public PCMessagerbase {
public:
	virtual void Login(string username, string password) {
		PCMessagerbase::PlaySound();
		PCMessagerbase::Connect();
		//**********
	}
	virtual void SendMassage(string message) {
		PCMessagerbase::WriteText();
		//*********
		PCMessagerbase::PlaySound();
	}
	virtual void SendPicture(Image image) {
		PCMessagerbase::PlaySound();
		PCMessagerbase::DrawShape();
		//*********
	}
};
class MobileMessageLite : public MobileMessagerbase {
public:
	virtual void Login(string username, string password) {
		MobileMessagerbase::Connect();
		//**********
	}
	virtual void SendMassage(string message) {
		MobileMessagerbase::WriteText();
		//*********
	}
	virtual void SendPicture(Image image) {
		MobileMessagerbase::DrawShape();
		//*********
	}
};
class MobileMessagePerfect : public MobileMessagerbase {
public:
	virtual void Login(string username, string password) {
		MobileMessagerbase::PlaySound();
		MobileMessagerbase::Connect();
		//**********
	}
	virtual void SendMassage(string message) {
		MobileMessagerbase::WriteText();
		//*********
		MobileMessagerbase::PlaySound();
	}
	virtual void SendPicture(Image image) {
		MobileMessagerbase::PlaySound();
		MobileMessagerbase::DrawShape();
		//*********
	}
};

void process() {
	//编译时装配
	Messager* m = new MobileMessagePerfect();
}

将上述代码如何修改为桥模式呢?为什么能够修改为桥模式呢?

动机:

  • 由于某些类型的固有实现逻辑,使得他们具有两个变化的维度,乃至多个维度的变化。
  • 如何应对多维度的变化?如何利用面向对象技术使得类型可以轻松地沿着两个乃至多个维度变化,而不引入额外的复杂度?

从上述子问题拆分方式进行业务代码实现,我们实现了很多类,基类1个,平台实现类2个,业务抽象类2*2个。然而在实际业务中,你的平台实现和业务抽象类将会更多,假设n个实现平台,m个业务抽象方法,那将会有1+n+m*n个类,类的个数随着平台和业务抽象急剧膨胀!

        下面代码是修改后代码,用桥模式的实现上述业务。基类Messager分为两个类,一个是Messager类,一个是MessagerImp类,平台的选择通过多态指针messagerImp实现,在运行时被确定。下面的代码将平台变化和业务变化两个维度进行,带动了行为的多态实现,这也就导致未修改前的基类Messager要分为两个类。实现了将抽象部分(业务功能)与实现部分(平台实现)分离,是他们可以独立的变化

        

class Messager { //第一个变化方向,平台变化
public:
	Messager(MessagerImp* imp):messagerImp(imp){} //初始化多态指针
	MessagerImp* messagerImp; //多态指针决定未来运行时是那个平台
	virtual void Login(string username, string password) = 0;
	virtual void SendMessage(string message) = 0;
	virtual void SendPicture(Image image) = 0;

	virtual ~Messager() {}
};
class MessagerImp { 
public:
	virtual void PlaySound() = 0;
	virtual void DrawShape() = 0;
	virtual void WriteText() = 0;
	virtual void Connect() = 0;

	virtual ~MessagerImp() {};
};

// 平台实现
class PCMessagerImp :public MessagerImp { //PC平台
public:
	virtual void PlaySound() {
		//**********
	}
	virtual void PlaySound() {
		//**********
	}
	virtual void WriteText() {
		//**********
	}
	virtual void Connect() {
		//**********
	}
};
class MobileMessagerImp :public MessagerImp { //移动平台
public:
	virtual void PlaySound() {
		//**********
	}
	virtual void PlaySound() {
		//**********
	}
	virtual void WriteText() {
		//**********
	}
	virtual void Connect() {
		//**********
	}
};
// 业务抽象
//第二个变化,业务的变化(简洁版和完美版)
class MessageLite:public Messager {
	
public:
	virtual void Login(string username, string password) {
		messagerImp->Connect();
		//**********
	}
	virtual void SendMassage(string message) {
		messagerImp->WriteText();
		//*********
	}
	virtual void SendPicture(Image image) {
		messagerImp->DrawShape();
		//*********
	}
};
class MessagePerfect : public Messager{
public:
	virtual void Login(string username, string password) {
		messagerImp->PlaySound();
		messagerImp->Connect();
		//**********
	}
	virtual void SendMassage(string message) {
		messagerImp->WriteText();
		//*********
		messagerImp->PlaySound();
	}
	virtual void SendPicture(Image image) {
		messagerImp->PlaySound();
		messagerImp->DrawShape();
		//*********
	}
};

void process() {
	//运行时装配
	MessagerImp* mImp = new PCMessagerImp();
	Messager* m = new Messager(mImp);
}

如下图所示是上述代码的桥模式类图

 总结:

  • Bridge模式使用“对象间的组合关系"解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自纬度的变化,即“子类化”它们。
  • Bridge模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。
  • Bridge模式的应用一般在“两个非常强的变化维度”,有时一个类也有多于两个的变化维度,这时可以使用Bridge的扩展模式。

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

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

相关文章

SpringBoot-Dubbo中的Customer怎么获取了注册中心的服务呢?

1.Dubbo中的Customer怎么获取了注册中心的服务呢? (1)要在pom文件中导入接口依赖 (2)在配置文件中指定服务中心的ip地址 (3)使用的dubbo自己的注解向服务中心中获取服务,并且将获取…

史上最简单:SpringCloud 集成 mybatis-plus(以若依微服务版本为例)

编者按:若依微服务版是基于Spring Boot、Spring Cloud & Alibaba的微服务的权限管理系统,也是笔者比较推荐的个人学习和企业实践都比较优秀的开源项目。 笔者也以此项目为例,介绍一下我自己是如何操作 SpringCloud 集成 mybatis-plus 的。…

API网关之Nginx作为网关的优势及实战

基于Nginx的网关的优势: 1 .速度更快、并发更高 单次请求或者高并发请求的环境下,Nginx都会比其他Web服务器响应的速度更快。一方面在正常情况下,单次请求会得到更快的响应,另一方面,在高峰期(如有数以万计的并发请求…

【Pytorch with fastai】第 20 章 :结语与问题

🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃 🎁欢迎各位→点赞…

开启linux的网络服务, FTP、SSH和NFS服务

在使用linux中开发的时候,我们可以选择启用一些网络服务方便我们进行开发,加快开发的进度。 现在很多用linux进行开发的工程师,他们大多都是在windows系统上安装虚拟机,然后在虚拟机中安装linux系统,然后在里面完成项目…

Java项目——表白墙(前后端连接+数据库存储)

前端的表白墙实现代码在之前的博客中有 Message类 表白墙中的每一个表白信息都由Message对象呈现,其包含form——表白者,to——被表白者,message——表白信息,以及一系列get和set方法 public class Message {private String fr…

我是如何构建自己的笔记系统的?

我是如何构建自己的笔记系统的? 关于笔记系统的重要性互联网上有许多的资料, 我这里将不再赘述. 下面我将直接介绍我的笔记从记录到整理文章发布的所有详细步骤和工具 我的笔记系统可能并不完善, 而且带着极强的个人倾向性, 只希望它能提供给你一种思考的方向 原文地址: https…

ArrayList 可以完全替代数组吗?

本文已收录到 GitHub AndroidFamily,有 Android 进阶知识体系,欢迎 Star。技术和职场问题,请关注公众号 [彭旭锐] 加入 Android 交流群。 前言 大家好,我是小彭。 在前面的文章里,我们学习了很多数据结构与算法思想…

【Nacos案例】

0、整体 整体项目概览 整体服务概览 1、新建父工程demo-nacos 删除src &#xff0c;切记 packaging&#xff1a;pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"ht…

[Apollo Cyber RT] Timer实现

Timer的实现方式 Timer有多种实现方式&#xff0c;CyberRT采用了时间轮(TimingWheel)方式。关于Timing Wheels的详细描述可以参考附录的链接。此处不赘述。 CyberRT Timer的类构成 实现细节 Timer Timer类是门户&#xff0c;但定时器真正的核心是TimingWheel。 Timer的定义…

索引的基础使用

索引&#xff1a; 分类&#xff1a; 功能逻辑&#xff1a;普通索引、唯一索引、主键索引、全文索引物理实现方式&#xff1a;聚簇索引&#xff0c;非聚簇索引作用字段个数&#xff1a;单列索引&#xff0c;联合索引 索引创建&#xff1a; --主键索引 CREATE TABLE dept( de…

SpringBoot的使用

一、Maven的环境搭建 暂时未完成.... 二、创建项目 创建完以后的目录如下&#xff1a; 然后配置pom.xml 再放入配置项 <!-- 2 我的依赖仓库源 , 首先配置仓库的服务器位置,首选阿里云&#xff0c;也可以配置镜像方式&#xff0c;效果雷同 --><repositories><re…

章节四:RASA 训练数据介绍

一、前言 一般来说&#xff0c;机器人可以跟人对话&#xff0c;机器人说什么是最难的&#xff0c;顶多是人工编写几种规则和模版来回复即可。但是要让机器人理解人的意图&#xff0c;确实非常难的事情。因为语言具有多样性&#xff0c;多义词&#xff0c;一语双关&#xff0c;…

872. 最大公约数(史上最详细讲解 7种算法,STL+算法标准实现)

一&#xff0c;什么是最大公约数 最大公约数&#xff08;Greatest Common Divisor&#xff09;指两个或多个整数共有约数中最大的一个。也称最大公因数、最大公因子&#xff0c;a&#xff0c; b的最大公约数记为&#xff08;a&#xff0c;b&#xff09;&#xff0c;同样的&…

测试架构工程师需要具备哪些能力 ?

目录 前言 为什么软件项目需要架构设计&#xff1f; 测试架构师需要解决什么问题&#xff1f; 测试架构师需要具备哪些能力&#xff1f; 测试工程师如何培养架构能力&#xff1f; 总结 重点&#xff1a;配套学习资料和视频教学 前言 相比于我们常见的研发架构师&#xf…

深入ftrace kprobe原理解析

Linux krpobe调试技术是内核开发者专门为了编译跟踪内核函数执行状态所涉及的一种轻量级内核调试技术&#xff0c;利用kprobe技术&#xff0c;内核开发人员可以在内核的绝大多数指定函数中动态插入探测点来收集所需的调试状态信息而基本不影响内核原有的执行流程。本章的是基于…

Spring-Mybatis整合 | 原理分析

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 文章目录▌环境搭建▌Mybatis流程回顾▌Mybatis-Spring整合SqlSessionTemplate方式SqlSessionTemplate分析configLocation & mapperLocations分析SqlSessionDaoSu…

ERD Online 4.0.3数据库在线建模(免费、更美、更稳定)

ERD Online 4.0.3❝ 全新升级&#xff0c;团队功能、权限管理、更美更稳定从这个版本&#xff0c;我们隆重推出低代码设计平台LOCO&#xff0c;见下文❞发展里程碑 4.0.3改动一览 功能完善 个人项目 个人项目即原有的项目管理&#xff0c;每个账号只能编辑自己的「个人项目」。…

linux下自动构建工具make:makefile

文章目录make/makefile介绍makefile的核心规则makefile的寻找规则makefile的伪目标什么是makefile&#xff1f;大多数人都应该是不太清楚的&#xff0c;因为现在人们基本都用着非常好的适合自己的IDE&#xff0c;而IDE为人们做了makefile该做的&#xff0c;从而导致大多数人并不…

同花顺_代码解析_技术指标_O

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 目录 OBOS OBV OBVFS OI指标 OSC OBOS 超买超卖指标 大盘指标。 输出超买超卖指标:上涨家数-下跌家数的N日异同移动平均 输出MAOBOS:OBOS的M日简单移动平均 1.指标上升至80时为超买&…