在我们设计C/C++ 程序的时候,有时需要两个类或者两个模块相互“认识”,或者两个模块间函数互相调用,假设我们正在开发一个网上商店,代表的网店客户的类必须要知道相关的账户。

UML图如下,这被称为环依赖,这两个类直接或间接地相互依赖。

一般我们都会采用结构体或类前置声明的方式,在解决此问题。

customer.h

#ifndef CUSTOMER_H_
#define CUSTOMER_H_class Account;
class Customer
{// ...void setAccount(Account* account);{customerAccount = account;}//...
private:Account* customerAccount;
};
#endif

account.h

#ifndef ACCOUNT_H_
#define ACCOUNT_H_
class Customer;
class Account
{public://...void setOwer(Customer* customer){ower = customer;}//...private:Customer* ower;
}
#endif

老实说上面的方式确实可以消除编译器的错误,但是这种解决方案不够好。

下面的调用示例,存在一个问题,当删除Account的实例,Customer的实例仍然存在,且内部的指向Account的指针为空。使用或解引用此指正会导致严重的问题。

#include "account.h"
#include "customer.h"//...
Account *account = new Accout{};
Customer *customer = new Customer{};
account->setOwer(customer);
customer->setAccount(account);

那有没有更好的做法呢,依赖倒置原则可以很好的解决此类问题。

依赖倒置原则

第一步是我们不在两个类中的其中一个访问另一个,相反,我们只通过接口进行访问。我们从Customer中提取Ower的接口,作为示例,Ower接口中声明一个纯虚函数,该函数必须由此接口类覆盖。

ower.h

#ifndef OWNER_H_
#define OWNER_H_#include <memory>
#include <string>class owner
{public:virtual ~owner()=default;virtual std::string getName() const = 0;
};
using OwnerPtr = std::shared_ptr<Owner>;
#endif

Customer.h

#ifndef CUSTOMER_H_
#define CUSTOMER_H_#include "Owner.h"
#include "Account.h"class Customer:public Owner
{public:void setAccount(AccountPtr account){customerAccount =   account;    }virtual std::string getName() const override{//return string}private:Account customerAccount;
};
using CustomerPtr = std::shared_ptr<Customer>;
#endif

account.h

#ifndef ACCOUNT_H_
#define ACCOUNT_H_#include "Owner.h"
class Account
{public:void setOwner(OwnerPtr owner){this->owner = owner;}private:OwnerPtr owner;
};
using AccountPtr = std::shared_ptr<Account>;

现在设计完发现这两个模块间消除了环依赖。

C/C++ 通过回调函数和信号槽的方式降低模块的耦合性

为了降低模块功能代码的耦合性,我们经常采用回调函数或者信号槽的方式来联系两个模块。

回调函数的方式:

a.h

#pragma once
#ifndef A_H_
#define A_H_
#include <stdio.h>int test(int c);#endif

a.c

#include "a.h"
int test(int c)
{c = 0x11112;return c;
}

b.h

#pragma once
#ifndef B_H_
#define B_H_
#include <stdio.h>typedef int (*PtrFunA)(int);int testb(PtrFunA, int c);
#endif

b.c

#include "b.h"int testb(PtrFunA a, int c)
{int ret = a(c);printf("%d\n", ret);return ret;
}

main.c

#include <stdio.h>
#include "a.h"
#include "b.h"
int main()
{testb(test,123);
}

这样做的好处降低代码的耦合性,是A模块的功能代码只写在A.C中。B.C的功能代码只写在B.C中,改进的后的回调函数可以用void*进行传参,在a.c中对void*进行判断,这是很多代码常做的操作。

信号槽的话则更加灵活性和代码的耦合度再次降低,后期在说,先写在这了。

C/C++ 相关低耦合代码的设计相关推荐

  1. 高内聚低耦合设计原则

    高内聚低耦合 高内聚低耦合是模块设计的基本原则.模块设计就像四世同堂居家过日子,妯娌婆媳吃大锅饭.柴米油盐不分你我很容易伤和气:如果亲兄弟明算账,每顿饭都AA又太显得生分,不利于和谐,因此把握好一个度 ...

  2. 什么是高内聚、低耦合

    起因:模块独立性指每个模块只完成系统要求的独立子功能,并且与其他模块的联系最少且接口简单,两个定性的度量标准――内聚性和耦合性. 内聚性又称块内联系.指单个模块的功能强度的度量,即一个模块内部各个元素 ...

  3. 你的代码是否按照高内聚、低耦合的原则来设计的?

    我们一直强调软件开发中要按照高内聚.低耦合的设计原则来做代码结构设计.c语言和c++不同,c语言面向过程.c++面向对象. 真正的项目中,要对业务升级,原来的业务函数需要保留,要保证老的功能继续维持, ...

  4. 多模块顺序_软件架构基础 3: 什么是好的模块化代码?高内聚、低耦合如何衡量?...

    0. 写在前面 什么是好的代码?好的代码应该模块化. 王垠在其<编程的智慧>中也提到,要"写模块化的代码".(不对人做评价,这篇文章写得是非常好的.) 如果你读过< ...

  5. 软件设计之——“高内聚低耦合”

    耦合度 一.什么是耦合度 软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准.划分摸块的一个准则就是高内聚低耦合. 耦合度(Coupling)是对模块间关联程度的度量.耦合的强弱取决与模块间接口 ...

  6. 软件设计原则:高内聚低耦合

    这是软件工程中的概念,是判断设计好坏的标准,主要是面向OO的设计,主要是看类的内聚性是否高,偶合度是否低. 一个程序有50个函数,这个程序执行得非常好:然而一旦你修改其中一个函数,其他49个函数都需要 ...

  7. 软件设计之——高内聚低耦合

    耦合度 一.什么是耦合度 软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准.划分摸块的一个准则就是高内聚低耦合. 耦合度(Coupling)是对模块间关联程度的度量.耦合的强弱取决与模块间接口 ...

  8. python模块化设计耦合度_模块化开发——高内聚低耦合

    前言:emmm最近都在赶进度,已经好久没输出了,接下来都使用MakeDown文档写文,推荐大家使用VsCode编译工具,加入Markdown Preview Enhanced插件,创建一个MD文件,复 ...

  9. 如何实现代码的高内聚低耦合

    之前在参加宋宝华老师的培训时,宋老师经常说写代码要做到高内聚低耦合,当时并不太理解其意义,只是感觉这句话是正确的,但是不知道具体如何操作,后来代码写的看的多了,才初窥门径,下面就是自己的一点经验总结. ...

最新文章

  1. 自制MVC之工具类插件一
  2. python3安装步骤mac-Mac 上安装python3——手把手教程
  3. python安装pandas模块-python安装numpy和pandas的方法步骤
  4. 再见,Eclipse...
  5. 【百度地图API1.1】修改文本标注的样式
  6. ES6学习笔记(二十二)ArrayBuffer
  7. Drainage Ditches - poj 1273(网络流模板)
  8. 使用七牛图片遇到的图片方向翻转问题
  9. vue-cli-3.0 axios 配置
  10. 【CNN】CNN是不是一种局部self-attention?
  11. [导入]关于中文文本的截取
  12. vmware虚拟机添加物理网卡与虚拟网卡
  13. Charles 实现电脑抓取手机包(解决手机不能上网问题)
  14. ESET NOD32 互联网安全软件和防毒软件 -简单,可靠的防护。
  15. 网页版简易计算器(仅加减乘除)
  16. TestCenter测试管理工具功能详解三(H)
  17. Kettle 8.2 打开spoon.bat后闪退的解决办法
  18. thinksns的部署
  19. Design Data-Intensive Applications 读书笔记三 查询语句
  20. 知名985北京师范大学,也改考408了!

热门文章

  1. 批量将记事本文本文件转为 UTF8 等编码格式
  2. 16.求两个数的最大公约数和最小公倍数
  3. 一码跑遍众多小程序,饿了么开源自研多端框架 MorJS
  4. Ubuntu系统连接Android真机调试
  5. 黑苹果与Windows系统时间不同步的解决办法
  6. android ormlite 查询,ORMLite查询日期
  7. 学人工智能必看!具体职业细分
  8. 安卓数据恢复_安卓手机禁广告、数据恢复
  9. 海外跨境电商商城源码-进出口电商平台网站-多语言多商户平台
  10. (c语言)求一元二次方程的根