C++通透讲解设计模式:依赖倒转(1)

server/2025/1/18 11:02:01/

依赖倒转

这是我认为的SOLID里面最重要的一个原则,当你掌握这种设计方式之后,会让别人在调用你的代码时爽很多。

C++20设计模式这本书中,依赖倒转写的很抽象。我这里将他的概念列出:

  1. 高层模块不应该依赖底层模块,它们都应该依赖抽象接口。
  2. 抽象接口不应该依赖细节,细节应该依赖抽象接口。

看到这两句话就觉得很抽象,对吧?

其实我总结出一个规律描述上面的关系:

类与类之间的关联行为应当由一个或者多个抽象管理和约束(我们最后再解释这句话)

废话不多说,上例子:

首先有个需求,我们现在要实现一个人接收电子邮件或者qq信息的场景,正常来说你可能会这样设计:

  1. 电子邮件和QQ还有人,三个对象本身都应有个类
  2. 邮件和QQ作为单独的一个对象,应该有一个方法getinfo获取他们的信息
  3. 而人作为对象,应该有执行这个getinfo的能力。

根据上面的逻辑,我们应该如下设计:


class Email {
public:void getInfo() {cout << "Email getInfo" << endl;}
};class QQ {
public:void getInfo() {cout << "QQ getInfo" << endl;}
};class Person {
public:void receive(Email& email) {email.getInfo();}void receive(QQ& qq) {qq.getInfo();}
};

看起来很不错!!写的代码也很整齐!没有学习设计模式之前我也是这样认为的。

但是我们忽略了一个问题:

  • 高层与低层之间的依赖关系

这会造成什么呢?

如果某一天,你不再负责维护这个项目,而是转而去做别的。这个项目交给一个其他人来维护。

此时正好有个需求是——添加一种新的软件叫做kk语音,那新来的那个家伙是不是就要开始写代码了?

此时,他也写了一个函数叫做recv_info

class QQ {
private:std::string info;
public:std::string recv_info() {return "recv_info" + info;}
};

之后这个人又走了,又来一个新人…

长此以往,由于代码变得很多,新的程序员需要将经历放在实现功能上时往往就会忽略整个项目的结构,加上没有对应的接口来进行规范,就出现一种方法类乱设计的情况。

知道某一天来了一个人,遇到主函数逻辑需要大改的情况,调用这个方法时发现什么呢?有的命名为getinfo有的命名为recv_info有的方法是返回值传参,有的是传出参数传参…

当然,现实情况不一定是这样,上面的例子是一种夸张的比喻(但是不是说没人这样写)。

最正确的方法应该是什么呢?

将这个方法设计成抽象类(抽象接口),让底层和高层的实例类(也被称为细节)都去依赖它。

// 依赖倒转原则
class IReceiver {
public:	virtual ~IReceiver() = default;virtual void getInfo() = 0;
};class Email : public IReceiver {
public:void getInfo() override {cout << "Email getInfo" << endl;}
};class QQ : public IReceiver {	
public:void getInfo() override {cout << "qq getInfo" << endl;}
};class Person {
public:// 里氏替换原则void receive(IReceiver& receiver) {receiver.getInfo();}
};

这样写的话,后来的人再添加功能时,就会优先注意到IReceiver这个接口,从而根据这个接口来写对应的函数,如果接口的返回值不能满足它,它会额外设计一个分离开的接口,促使下一个人遵守另一条设计原则——接口隔离原则。

总而言之,返回我一开始总结的那句话:会发现高层和底层模块之间的依赖就是类与类之间的关联行为(getinfo)应当由一个或多个抽象管理和约束(设计成接口后,方便维护)

这就是依赖倒转原则。

当然,更先进的做法其实还有一种方法,叫做依赖注入,下次有机会再讲!


http://www.ppmy.cn/server/159338.html

相关文章

软考信安22~网站安全需求分析与安全保护工程

1、网站安全威胁与需求分析 1.1、网站安全概念 网站安全主要是有关网站的机密性、完整性、可用性及可控性。 网站的机密性是指网站信息及相关数据不被授权查看或泄露。 网站的完整性是指网站的信息及数据不能非授权修改,网站服务不被劫持。 网站的可用性是指网站可以待续…

SUN的J2EE与微软的DNA

J2EE(Java 2 Platform, Enterprise Edition) 和 微软的DNA(Distributed interNet Architecture) 是两种面向企业级应用开发的架构,它们在设计理念、技术栈和应用场景上各有特点。以下是对它们的详细介绍与对比: SUN的J2EE(Java 2 Platform, Enterprise Edition) 简介 …

windows下安装并使用node.js

一、下载Node.js 选择对应你系统的Node.js版本下载 Node.js官网下载地址 Node.js中文网下载地址??? 这里我选择的是Windows64位系统的Node.js20.18.0&#xff08;LTS长期支持版本&#xff09;版本的.msi安装包程序 官网下载&#xff1a; 中文网下载&#xff1a; 二、安…

【开源宝藏】Jeepay VUE和React构建WebSocket通用模板

WebSocket 服务实现&#xff1a;Spring Boot 示例 在现代应用程序中&#xff0c;WebSocket 是实现双向实时通信的重要技术。本文将介绍如何使用 Spring Boot 创建一个简单的 WebSocket 服务&#xff0c;并提供相关的代码示例。 1. WebSocket 简介 WebSocket 是一种在单个 TC…

Linux下的dev,sys和proc(TODO)

&#xff08;TODO&#xff09; 还有一个sysfs 在 Linux 系统中&#xff0c;/dev、/sys 和 /proc 是三个特殊的虚拟文件系统目录&#xff0c;它们各自有特定的用途&#xff0c;主要用于与设备和内核交互。以下是它们的详细区别和功能说明&#xff1a; 1. /dev&#xff08;Devi…

基于SpringBoot的装修公司管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

Kafka——两种集群搭建详解 k8s

1、简介 Kafka是一个能够支持高并发以及流式消息处理的消息中间件&#xff0c;并且Kafka天生就是支持集群的&#xff0c;今天就主要来介绍一下如何搭建Kafka集群。 Kafka目前支持使用Zookeeper模式搭建集群以及KRaft模式&#xff08;即无Zookeeper&#xff09;模式这两种模式搭…

关于Nvidia显卡在windows系统下存在部分软件屏闪/闪烁问题与解决方法

问题描述 部分软件GUI在使用时一直闪烁/闪屏&#xff0c;包括拖动侧栏与切换子页面时会留下残影。本人遇到发生该现象的桌面应用包括且不限于docker desktop, meta quest link, Vortex, Tabby Terminal等。 本人环境&#xff1a; 操作系统&#xff1a;windows11 显卡&#xf…