当前位置: 首页 > news >正文

设计心得——解耦的实现技术

一、说明

在前面的“设计心得——解耦”中,对解耦进行了高层次的抽象说明。本篇则对在实践中常用的解耦技术进行逐一分析说明,以期为开发者能更从理论到实践搭建一个桥梁。至于大家能够如何更好的在自己的项目中进行解耦的实践,就需要不断的进行总结分析,有一个否定之否定的过程。

二、解耦的技术

实现解耦的技术和手段非常多,常见的有以下几种:
1、抽象接口
通过接口来实现类间的解耦是非常常见的手段,在C++中一般是使用抽象类中的纯虚函数来进行接口抽象。通过具体的实现类来完成抽象接口中的统一接口,从而达到解耦的目的。类似下面的这种:

#include <iostream>
#include <memory>// 抽象接口类 Shape
class Shape {
public:virtual void draw() const = 0;virtual ~Shape() = default;
};// 子类Circle
class Circle : public Shape {
public:void draw() const override {std::cout << "Drawing a Circle" << std::endl;}
};// 子类 Rectangle
class Rectangle : public Shape {
public:void draw() const override {std::cout << "Drawing a Rectangle" << std::endl;}
};void drawShape(const std::shared_ptr<Shape>& shape) {shape->draw();
}int main() {auto circle = std::make_shared<Circle>();auto rectangle = std::make_shared<Rectangle>();drawShape(circle);drawShape(rectangle);return 0;
}

例程简单明了,一眼就能看出来接口的意思。另外模块间的API接口其实也可以划到这部分:

int open(const char *pathname, int flags, mode_t mode);

Linux系统的文件打开API函数。
2、设计模式
在设计模式中提供了一些解耦的手段,如工厂模式、策略模式和命令模式等等

#include <iostream>
#include <memory>
//接口抽象
class MoveStrategy {
public:virtual ~MoveStrategy() = default;virtual void move() const = 0;
};
//具体策略
class WalkStrategy : public MoveStrategy {
public:void move() const override {std::cout << "The Role is walking." << std::endl;}
};class RunStrategy : public MoveStrategy {
public:void move() const override {std::cout << "The Role is running." << std::endl;}
};class JumpStrategy : public MoveStrategy {
public:void move() const override {std::cout << "The Role is jumping." << std::endl;}
};
//角色类
class Role {
private:std::shared_ptr<MoveStrategy> moveStrategy;public:Role(std::shared_ptr<MoveStrategy> strategy): moveStrategy(std::move(strategy)) {}void setMoveStrategy(std::shared_ptr<MoveStrategy> strategy) {moveStrategy = std::move(strategy);}void move() const {moveStrategy->move();}
};
int main() {// 创建角色,并设置其移动策略auto role = std::make_shared<Role>(std::make_shared<WalkStrategy>());role->move();//使用跑动策略role->setMoveStrategy(std::make_shared<RunStrategy>());role->move();//使用跳跃策略role->setMoveStrategy(std::make_shared<JumpStrategy>());role->move();return 0;
}

其它设计模式基本的方法类似。
3、控制反转(依赖注入)
这个例子非常多,前面也刚刚分析过就不再举例了。
4、泛型编程(模板编程 )
模板编程的优势在于适应性更强,编码灵活,便于优化,但使用不当可能会引起代码膨胀等问题。但最主要的是引入的复杂性,要根据情况取舍,看一个简单的比较处理:

#include <iostream>
#include <type_traits>template <typename T>
decltype(auto) compare(const T& a, const T& b)  {return a < b;
}struct MyType {int value;MyType(int v) : value(v) {}bool operator<(const MyType& other) const {return value < other.value;}
};int main() {int x = 5, y = 10;double a = 3.14, b = 2.71;MyType m1(1), m2(2);compare(x,y);compare(a,b);compare(m1,m2);return 0;
}

5、服务隔离
也就常提到的面向服务编程,包括消息队列服务、流服务和远程服务

//services
class PostProcess(http_request request){
virtual std::string recvRequest(http_request request) = 0;
};
class PostPlatform(http_request request):public PostProcess{
virtual std::string recvRequest(http_request request){std::cout<<"Platform recv request!"<<std::endl;return "platform";
}
};
class PostMerchant(http_request request):public PostProcess{
virtual std::string recvRequest(http_request request){std::cout<<"Merchant recv request!"<<std::endl;return "merchant";
}
};
//client
std::string sendRequest(PostProcess *p,http_request request){auto s = p->recvRequest(request)return s;
}
int main() {PostPlatform pp;http_request request("exchange goods");sendRequest(&pp,request);return 0;
}

6、其它
这一其它就多了,不过除了上面那几个技术,象COM技术、插件技术等等都是用得虽然不多,但名气可不小的。此处就不再举例 ,有兴趣的可以看看一些开源框架或源码,如MySql的源码中就使用了插件技术。

三、比较和应用

在上面的几种解耦技术中,对大多数C++程序员来说,经常使用的还是在前四个居多。但无论哪种应用,一个前提就是不能太复杂,所以泛型编程可能对很多小伙伴来说就又被剔除了。而控制反转和设计模式一般来说都和一定场景有关,所以最后留下来的,就是一个,抽象接口来实现解耦。
或者回过头来说,抽象接口是后面所有的解耦手段的基础,掌握了接口抽象的能力,就具备在设计层次向更高一层前进的能力。

四、总结

设计是一个不断沉淀的过程,没有人可能一下就掌握了设计的全部精髓。这就和一个人的成长一样,从婴儿到成为一个健硕的青年,中间可能会经过无数的大大小小的错误,既有身体疾病上的成长的过程,也有思想不断成熟的过程。
所以,设计只是一个人思想的外延。它既受主观的影响也受外面客观的实践的影响。

相关文章:

设计心得——解耦的实现技术

一、说明 在前面的“设计心得——解耦”中&#xff0c;对解耦进行了高层次的抽象说明。本篇则对在实践中常用的解耦技术进行逐一分析说明&#xff0c;以期为开发者能更从理论到实践搭建一个桥梁。至于大家能够如何更好的在自己的项目中进行解耦的实践&#xff0c;就需要不断的…...

计算机毕业设计SpringBoot+Vue.jst在线文档管理系统(源码+LW文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

在windows下安装windows+Ubuntu16.04双系统(下)

这篇文章的内容主要来源于这篇文章&#xff0c;为正式安装windowsUbuntu16.04双系统部分。在正式安装前&#xff0c;若还没有进行前期准备工作&#xff08;1.分区2.制作启动u盘&#xff09;&#xff0c;见《在windows下安装windowsUbuntu16.04双系统(上)》 二、正式安装Ubuntu …...

一文讲解Redis为什么读写性能高以及I/O复用相关知识点

Redis为什么读写性能高呢&#xff1f; Redis 的速度⾮常快&#xff0c;单机的 Redis 就可以⽀撑每秒十几万的并发&#xff0c;性能是 MySQL 的⼏⼗倍。原因主要有⼏点&#xff1a; ①、基于内存的数据存储&#xff0c;Redis 将数据存储在内存当中&#xff0c;使得数据的读写操…...

TPU(Tensor Processing Unit)详解

一、什么是TPU&#xff1f; TPU&#xff08;Tensor Processing Unit&#xff0c;张量处理器&#xff09;是谷歌专门为机器学习任务设计的定制化ASIC芯片&#xff0c;旨在加速神经网络训练与推理。其核心目标是针对矩阵运算&#xff08;如矩阵乘加&#xff09;优化硬件架构&…...

Ubuntu20.04.2安装Vmware tools

软件版本&#xff1a;Vmware Workstation Pro 17.6.2 操作系统镜像文件&#xff1a;ubuntu-20.04.2-desktop-amd64 方式1&#xff1a;用iso镜像安装 没用这种方法&#xff0c;太麻烦 方式2&#xff1a;用apt安装Open VM Tools 如果你使用的是较新的Ubuntu版本&#xff08;如…...

检测服务端口是否开放的常用方法

检测服务端口是否开放的常用方法 文章目录 检测服务端口是否开放的常用方法背景使用nc命令使用 telnet 命令使用 curl 命令使用 openssl 命令使用 Python 脚本,socket连接使用 bash 内建命令:使用 nmap:总结 背景 有时候需要测试网络是否连通&#xff0c;端口是否开放&#xf…...

muduo源码阅读:socket常见操作及一些补充

TCP连接和释放 一个典型的TCP连接、通信过程&#xff1a; &#xff08;假设有资源的一端是服务器端&#xff09; 服务器会启用一个监听循环&#xff0c;不断接受client连接请求(三次握手建立连接), 进行数据通信&#xff0c;通信完成以后断开连接(四次挥手断开连接)。 对于…...

虚拟表格实现全解析

在数据展示越来越复杂的今天&#xff0c;大量数据的渲染就像是“满汉全席”——如果把所有菜肴一次性摆上桌&#xff0c;既浪费资源也让人眼花缭乱。幸运的是&#xff0c;我们有两种选择&#xff1a; 自己动手&#xff1a;通过二次封装 Element Plus 的表格组件&#xff0c;实…...

使用 Grafana 监控 Spring Boot 应用

随着软件开发领域的不断发展&#xff0c;监控和可观测性已成为确保系统可靠性和性能的关键实践。Grafana 是一个功能强大的开源工具&#xff0c;能够为来自各种来源的监控数据提供丰富的可视化功能。在本篇博客中&#xff0c;我们将探讨如何将 Grafana 与 Spring Boot 应用程序…...

使用Socket编写超牛的http服务器和客户端(一)

实现一个高性能的基于 IOCP(I/O Completion Ports)的 HTTP 服务器,支持多线程、动态线程池调整和路由处理。 主要功能和特性 IOCP 模型: 使用多个 IOCP 句柄(IOCP_COUNT),将客户端连接均匀分配到不同的 IOCP 上,减少线程竞争。 工作线程使用 GetQueuedCompletionStatu…...

python turtle模块有哪几种命令

python turtle模块命令的分类&#xff1a; 1、运动命令 2、笔画控制命令 3、其他命令...

【Transformer架构】

目录 一、Transformer介绍 1.1 Transformer的诞生 1.2 什么是Transformer 1.3 Transformer的优势 1.4 Transformer的市场 二、Transformer架构 2.1 Transformer模型的作用 2.2 Transformer总体架构图 2.2.1 Transformer总体架构 2.2.2 输入部分 2.2.3 输出部分 2.2.…...

unity学习50:NavMeshAgent 区域Areas和cost

目录 1 NavMeshAgent 区域和成本的问题 2 区域Areas 2.1 区域和颜色 2.2 区域和成本 2.3 区域成本的作用 2.4 地图测试准备 2.5 如何实现 2.5.1 unity的2022之前的老版本 2.5.2 unity的2022之后的新版本 2.6 如果测试失败&#xff0c;是因为没有bake 2.7 测试前&…...

Blender小技巧和注意事项

1.雕刻模式如果没反应,需要将模式转换成编辑模式 2. 鼠标移到大纲 点击 小键盘的. / 大键盘句号 , 在大纲视图快速找到选中物体 3.打包图像等数据进Blender文件中,可以防止丢失 4.拍摄小物体用长焦镜头 , 焦距120mm左右...

Python常见面试题的详解15

1. 死锁&#xff08;Deadlock&#xff09; 死锁指的是在多线程或者多进程的运行环境中&#xff0c;两个或多个线程&#xff08;进程&#xff09;彼此等待对方释放所占用的资源&#xff0c;进而陷入无限期等待的僵局&#xff0c;最终导致程序无法继续推进。 必要条件 互斥条件…...

代码审计初探

学会了基础的代码审计后&#xff0c;就该提高一下了&#xff0c;学一下一些框架的php代码审计 先从一些小众的、已知存在漏洞的cms入手 phpems php的一款开源考试系统 源码下载 https://down.chinaz.com/soft/34597.htm 环境部署 windows审计&#xff0c;把相关文件放到phps…...

Spring面试题2

1、compareable和compactor区别 定义与包位置:Comparable是一个接口&#xff0c;位于java.lang包,需要类去实现接口&#xff1b;而Compactor是一个外部比较器&#xff0c;位于java.util包 用法&#xff1a;Comparable只需要实现int compareTo(T o) 方法&#xff0c;比较当前对…...

Linux 权限系统和软件安装(二):深入理解 Linux 权限系统

在 Linux 的世界里&#xff0c;权限系统犹如一位忠诚的卫士&#xff0c;严密守护着系统中的文件与目录&#xff0c;确保只有具备相应权限的用户才能进行操作。与其他一些操作系统不同&#xff0c;Linux 并不依据文件后缀名来标识文件的操作权限&#xff0c;而是构建了一套独特且…...

二:前端发送POST请求,后端获取数据

接着一&#xff1a;可以通过端口访问公网IP之后 二需要实现&#xff1a;点击飞书多维表格中的按钮&#xff0c;向服务器发送HTTP请求&#xff0c;并执行脚本程序 向服务器发送HTTP请求&#xff1a; 发送请求需要明确一下几个点 请求方法&#xff1a; 由于是向服务器端发送值…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...

密码学基础——SM4算法

博客主页&#xff1a;christine-rr-CSDN博客 ​​​​专栏主页&#xff1a;密码学 &#x1f4cc; 【今日更新】&#x1f4cc; 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 ​编辑…...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...