当前位置: 首页 > 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; 由于是向服务器端发送值…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...