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

news/2025/2/24 0:49:57

一、说明

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

二、解耦的技术

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

四、总结

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


http://www.niftyadmin.cn/n/5863889.html

相关文章

将 Vue 项目打包后部署到 Spring Boot 项目中的全面指南

将 Vue 项目打包后部署到 Spring Boot 项目中的全面指南 在现代 Web 开发中&#xff0c;前后端分离架构已经成为主流。然而&#xff0c;在某些场景下&#xff0c;我们可能需要将前端项目&#xff08;如 Vue&#xff09;与后端项目&#xff08;如 Spring Boot&#xff09;集成部…

行业分析---对自动驾驶规控算法未来的思考

1 前言 随着自动驾驶端到端大模型的兴起&#xff0c;小鹏、华为、理想、蔚来、小米等公司都对自动驾驶业务部进行了组织架构的调整&#xff0c;准备应对新的或者更高级别的自动驾驶研发任务。 近几年由于自动驾驶技术的快速发展&#xff0c;不少从业者觉得相关职业的未来充满了…

使用IDEA提交SpringBoot项目到Gitee上

登录Gitee并新建仓库 创建本地仓库 提交本地代码到本地仓库 提交本地代码到远程仓库

Redis 深度解析:高性能缓存与分布式数据存储的核心利器

在现代分布式系统中&#xff0c;性能与可扩展性是开发者面临的核心挑战之一。为了应对高并发、低延迟的需求&#xff0c;缓存技术成为了不可或缺的解决方案。而 Redis&#xff0c;作为一款开源的、基于内存的键值存储系统&#xff0c;凭借其卓越的性能、丰富的数据结构和高可用…

我用Ai学Android Jetpack Compose之LinearProgressIndicator

本篇&#xff0c;我们来学习LinearProgressIndicator&#xff0c;答案来自 通义千问 Q:我想学习LinearProgressIndicator&#xff0c;麻烦你介绍一下 当然可以&#xff01;LinearProgressIndicator 是 Jetpack Compose 中的一个组件&#xff0c;用于显示线性进度条。它非常适…

Java 中的 List 和 Map:全面解析与实际应用

在 Java 编程中&#xff0c;List 和 Map 是两种非常重要的数据结构&#xff0c;广泛应用于各种场景。它们提供了灵活的方式来存储和操作数据&#xff0c;能够帮助开发者更高效地实现业务逻辑。本文将深入解析 Java 中 List 和 Map 的定义与使用&#xff0c;并通过具体代码示例展…

ubuntu docker 安装 deepseek anythingllm/openwebui教程

全新服务器安装起始&#xff1a; 1. 安装ubuntu到服务器中 2. 安装docker 安装教程 ubuntu 安装 docker详细教程_ubuntu安装教程docker-CSDN博客 3. 安装 ollama docker pull ollama/ollama 3.1 创建 存储目录 &#xff08;示例放在/home/ollama中&#xff09; cd /home/ …

2025高维多目标优化:基于导航变量的多目标粒子群优化算法(NMOPSO)的无人机三维路径规划,MATLAB代码

一、NMOPSO介绍 基于导航变量的多目标粒子群优化算法&#xff08;Navigation Variable-based Multi-Objective Particle Swarm Optimization, NMOPSO&#xff09;是一种专门用于无人机三维路径规划的先进算法。该算法通过将路径规划问题建模为一个多目标优化问题&#xff0c;并…