设计心得——解耦的实现技术
一、说明
在前面的“设计心得——解耦”中,对解耦进行了高层次的抽象说明。本篇则对在实践中常用的解耦技术进行逐一分析说明,以期为开发者能更从理论到实践搭建一个桥梁。至于大家能够如何更好的在自己的项目中进行解耦的实践,就需要不断的进行总结分析,有一个否定之否定的过程。
二、解耦的技术
实现解耦的技术和手段非常多,常见的有以下几种:
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++程序员来说,经常使用的还是在前四个居多。但无论哪种应用,一个前提就是不能太复杂,所以泛型编程可能对很多小伙伴来说就又被剔除了。而控制反转和设计模式一般来说都和一定场景有关,所以最后留下来的,就是一个,抽象接口来实现解耦。
或者回过头来说,抽象接口是后面所有的解耦手段的基础,掌握了接口抽象的能力,就具备在设计层次向更高一层前进的能力。
四、总结
设计是一个不断沉淀的过程,没有人可能一下就掌握了设计的全部精髓。这就和一个人的成长一样,从婴儿到成为一个健硕的青年,中间可能会经过无数的大大小小的错误,既有身体疾病上的成长的过程,也有思想不断成熟的过程。
所以,设计只是一个人思想的外延。它既受主观的影响也受外面客观的实践的影响。
相关文章:
设计心得——解耦的实现技术
一、说明 在前面的“设计心得——解耦”中,对解耦进行了高层次的抽象说明。本篇则对在实践中常用的解耦技术进行逐一分析说明,以期为开发者能更从理论到实践搭建一个桥梁。至于大家能够如何更好的在自己的项目中进行解耦的实践,就需要不断的…...
计算机毕业设计SpringBoot+Vue.jst在线文档管理系统(源码+LW文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
在windows下安装windows+Ubuntu16.04双系统(下)
这篇文章的内容主要来源于这篇文章,为正式安装windowsUbuntu16.04双系统部分。在正式安装前,若还没有进行前期准备工作(1.分区2.制作启动u盘),见《在windows下安装windowsUbuntu16.04双系统(上)》 二、正式安装Ubuntu …...
一文讲解Redis为什么读写性能高以及I/O复用相关知识点
Redis为什么读写性能高呢? Redis 的速度⾮常快,单机的 Redis 就可以⽀撑每秒十几万的并发,性能是 MySQL 的⼏⼗倍。原因主要有⼏点: ①、基于内存的数据存储,Redis 将数据存储在内存当中,使得数据的读写操…...
TPU(Tensor Processing Unit)详解
一、什么是TPU? TPU(Tensor Processing Unit,张量处理器)是谷歌专门为机器学习任务设计的定制化ASIC芯片,旨在加速神经网络训练与推理。其核心目标是针对矩阵运算(如矩阵乘加)优化硬件架构&…...
Ubuntu20.04.2安装Vmware tools
软件版本:Vmware Workstation Pro 17.6.2 操作系统镜像文件:ubuntu-20.04.2-desktop-amd64 方式1:用iso镜像安装 没用这种方法,太麻烦 方式2:用apt安装Open VM Tools 如果你使用的是较新的Ubuntu版本(如…...
检测服务端口是否开放的常用方法
检测服务端口是否开放的常用方法 文章目录 检测服务端口是否开放的常用方法背景使用nc命令使用 telnet 命令使用 curl 命令使用 openssl 命令使用 Python 脚本,socket连接使用 bash 内建命令:使用 nmap:总结 背景 有时候需要测试网络是否连通,端口是否开放…...
muduo源码阅读:socket常见操作及一些补充
TCP连接和释放 一个典型的TCP连接、通信过程: (假设有资源的一端是服务器端) 服务器会启用一个监听循环,不断接受client连接请求(三次握手建立连接), 进行数据通信,通信完成以后断开连接(四次挥手断开连接)。 对于…...
虚拟表格实现全解析
在数据展示越来越复杂的今天,大量数据的渲染就像是“满汉全席”——如果把所有菜肴一次性摆上桌,既浪费资源也让人眼花缭乱。幸运的是,我们有两种选择: 自己动手:通过二次封装 Element Plus 的表格组件,实…...
使用 Grafana 监控 Spring Boot 应用
随着软件开发领域的不断发展,监控和可观测性已成为确保系统可靠性和性能的关键实践。Grafana 是一个功能强大的开源工具,能够为来自各种来源的监控数据提供丰富的可视化功能。在本篇博客中,我们将探讨如何将 Grafana 与 Spring Boot 应用程序…...
使用Socket编写超牛的http服务器和客户端(一)
实现一个高性能的基于 IOCP(I/O Completion Ports)的 HTTP 服务器,支持多线程、动态线程池调整和路由处理。 主要功能和特性 IOCP 模型: 使用多个 IOCP 句柄(IOCP_COUNT),将客户端连接均匀分配到不同的 IOCP 上,减少线程竞争。 工作线程使用 GetQueuedCompletionStatu…...
python turtle模块有哪几种命令
python turtle模块命令的分类: 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 如果测试失败,是因为没有bake 2.7 测试前&…...
Blender小技巧和注意事项
1.雕刻模式如果没反应,需要将模式转换成编辑模式 2. 鼠标移到大纲 点击 小键盘的. / 大键盘句号 , 在大纲视图快速找到选中物体 3.打包图像等数据进Blender文件中,可以防止丢失 4.拍摄小物体用长焦镜头 , 焦距120mm左右...
Python常见面试题的详解15
1. 死锁(Deadlock) 死锁指的是在多线程或者多进程的运行环境中,两个或多个线程(进程)彼此等待对方释放所占用的资源,进而陷入无限期等待的僵局,最终导致程序无法继续推进。 必要条件 互斥条件…...
代码审计初探
学会了基础的代码审计后,就该提高一下了,学一下一些框架的php代码审计 先从一些小众的、已知存在漏洞的cms入手 phpems php的一款开源考试系统 源码下载 https://down.chinaz.com/soft/34597.htm 环境部署 windows审计,把相关文件放到phps…...
Spring面试题2
1、compareable和compactor区别 定义与包位置:Comparable是一个接口,位于java.lang包,需要类去实现接口;而Compactor是一个外部比较器,位于java.util包 用法:Comparable只需要实现int compareTo(T o) 方法,比较当前对…...
Linux 权限系统和软件安装(二):深入理解 Linux 权限系统
在 Linux 的世界里,权限系统犹如一位忠诚的卫士,严密守护着系统中的文件与目录,确保只有具备相应权限的用户才能进行操作。与其他一些操作系统不同,Linux 并不依据文件后缀名来标识文件的操作权限,而是构建了一套独特且…...
二:前端发送POST请求,后端获取数据
接着一:可以通过端口访问公网IP之后 二需要实现:点击飞书多维表格中的按钮,向服务器发送HTTP请求,并执行脚本程序 向服务器发送HTTP请求: 发送请求需要明确一下几个点 请求方法: 由于是向服务器端发送值…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
