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

一、说明

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

二、解耦的技术

实现解耦的技术和手段非常多,常见的有以下几种:

1、抽象接口

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

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接口其实也可以划到这部分:

c 复制代码
int open(const char *pathname, int flags, mode_t mode);

Linux系统的文件打开API函数。

2、设计模式

在设计模式中提供了一些解耦的手段,如工厂模式、策略模式和命令模式等等

c 复制代码
#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、泛型编程(模板编程 )

模板编程的优势在于适应性更强,编码灵活,便于优化,但使用不当可能会引起代码膨胀等问题。但最主要的是引入的复杂性,要根据情况取舍,看一个简单的比较处理:

c 复制代码
#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、服务隔离

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

c 复制代码
//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++程序员来说,经常使用的还是在前四个居多。但无论哪种应用,一个前提就是不能太复杂,所以泛型编程可能对很多小伙伴来说就又被剔除了。而控制反转和设计模式一般来说都和一定场景有关,所以最后留下来的,就是一个,抽象接口来实现解耦。

或者回过头来说,抽象接口是后面所有的解耦手段的基础,掌握了接口抽象的能力,就具备在设计层次向更高一层前进的能力。

四、总结

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

所以,设计只是一个人思想的外延。它既受主观的影响也受外面客观的实践的影响。

相关推荐
QiLinkOS1 小时前
《打破“用爱发电”:一种基于 Gitee 与时间戳的开源权益分配机制探索》
c语言·数据结构·c++·科技·算法·gitee·开源
Irissgwe1 小时前
c++STL--string类
c++·stl·string
Irissgwe2 小时前
c++类型转换
c++·类型转换·explicit·static_cast·const_cast·dynamic_cast·rtti
智者知已应修善业2 小时前
【51单片机用T0定时器方式1,实现0.5S的时间间隔实现第一次一个灯亮、第二次二个灯亮,直到全部灯亮,然后重复整个过程】2023-12-29
c++·经验分享·笔记·算法·51单片机
智者知已应修善业2 小时前
【51单片机4位静态数码管显示1234】2023-11-14
c++·经验分享·笔记·算法·51单片机
抓虾爪2 小时前
ST意法代理商粤科源兴丨LSM6DS3全系列现货库存,LSM6DS3TR-C当天可发
c++
妙为2 小时前
unreal engine5.7.4,创建ThirdPerson第三人称模版,类型是c++崩溃
c++·ue5·虚幻·unreal engine5
郝学胜_神的一滴2 小时前
Qt 高级开发 021:零基础吃透 QVBoxLayout 垂直布局
c++·qt
Boom_Shu3 小时前
长方形的关系
数据结构·c++·算法
思麟呀3 小时前
C++11并发编程:call_once一次性执行+atomic原子类型+CAS无锁编程+自旋锁
linux·开发语言·jvm·c++·windows