当前位置: 首页 > news >正文

C++中的八大设计原则

目录

摘要

C+中的8大设计原则

1. 单一职责原则 (Single Responsibility Principle, SRP)

2. 开放封闭原则 (Open/Closed Principle, OCP)

3. 里氏替换原则 (Liskov Substitution Principle, LSP)

4. 依赖倒置原则 (Dependency Inversion Principle, DIP)

5. 接口隔离原则 (Interface Segregation Principle, ISP)

6. 迪米特法则 (Law of Demeter, LoD)

7. 合成复用原则 (Composite Reuse Principle, CRP)

8. 最少知识原则 (Least Knowledge Principle, LKP)

C++中的23种设计模式


摘要

C++ 中的八大设计原则可以帮助我们创建高内聚、低耦合的代码。

C+中的8大设计原则

1. 单一职责原则 (Single Responsibility Principle, SRP)

- 一个类应该只有一个引起变化的原因,即一个类只负责一个职责。可以提高类的可读性和可维护性,降低类的复杂度,但可能导致类的数量增加,进而增加系统设计的复杂性。

class UserManager {
public:void createUser(std::string username, std::string password) {// 创建用户}void deleteUser(std::string username) {// 删除用户}void generateUserReport(std::string username) {// 生成用户报告}void sendNotification(std::string message) {// 发送通知}
};// 应用SRP后
class UserCreator {
public:void createUser(std::string username, std::string password) {// 创建用户}
};class UserDeleter {
public:void deleteUser(std::string username) {// 删除用户}
};class UserReporter {
public:void generateUserReport(std::string username) {// 生成用户报告}
};class NotificationSender {
public:void sendNotification(std::string message) {// 发送通知}
};

2. 开放封闭原则 (Open/Closed Principle, OCP)

- 软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。可以提高系统的可扩展性,减少修改代码引入错误的风险,但需要仔细设计抽象层次,可能增加系统的复杂度。

class PaymentProcessor {
public:void processPayment(std::string paymentType) {if (paymentType == "CreditCard") {// 处理信用卡支付} else if (paymentType == "PayPal") {// 处理PayPal支付}}
};// 应用OCP后
class IPayment {
public:virtual void processPayment() = 0;
};class CreditCardPayment : public IPayment {
public:void processPayment() override {// 处理信用卡支付}
};class PayPalPayment : public IPayment {
public:void processPayment() override {// 处理PayPal支付}
};class PaymentProcessor {
public:void processPayment(IPayment* payment) {payment->processPayment();}
};

3. 里氏替换原则 (Liskov Substitution Principle, LSP)

- 子类对象应该能够替换掉基类对象且程序的行为不变。可以保证继承体系的正确性,增强代码的可替代性和可扩展性,但可能需要更多的抽象和接口设计,增加设计复杂度。

class Rectangle {
public:virtual void setWidth(double width) {this->width = width;}virtual void setHeight(double height) {this->height = height;}double getArea() {return width * height;}
protected:double width;double height;
};class Square : public Rectangle {
public:void setWidth(double width) override {this->width = width;this->height = width;}void setHeight(double height) override {this->width = height;this->height = height;}
};void process(Rectangle& r) {r.setWidth(5);r.setHeight(4);assert(r.getArea() == 20); // Square 不能替代 Rectangle
}

4. 依赖倒置原则 (Dependency Inversion Principle, DIP)

- 高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于具体,具体应该依赖于抽象。可以减少类之间的耦合,提高系统的灵活性和可维护性,但需要更多的抽象和接口设计,增加设计复杂度。

class Keyboard {
public:std::string getInput() {return "User input";}
};class Monitor {
public:void display(std::string text) {// 显示文本}
};class Computer {
public:void run() {std::string input = keyboard.getInput();monitor.display(input);}
private:Keyboard keyboard;Monitor monitor;
};// 应用DIP后
class IInputDevice {
public:virtual std::string getInput() = 0;
};class IOutputDevice {
public:virtual void display(std::string text) = 0;
};class Keyboard : public IInputDevice {
public:std::string getInput() override {return "User input";}
};class Monitor : public IOutputDevice {
public:void display(std::string text) override {// 显示文本}
};class Computer {
public:Computer(IInputDevice* inputDevice, IOutputDevice* outputDevice): inputDevice(inputDevice), outputDevice(outputDevice) {}void run() {std::string input = inputDevice->getInput();outputDevice->display(input);}
private:IInputDevice* inputDevice;IOutputDevice* outputDevice;
};

5. 接口隔离原则 (Interface Segregation Principle, ISP)

- 客户端不应该被迫依赖它不使用的方法,即类间的依赖关系应该建立在最小的接口上。可以减少代码的冗余,提高系统的灵活性和可维护性,但可能导致接口数量增加,进而增加系统设计的复杂性。

class IWorker {
public:virtual void work() = 0;virtual void eat() = 0;
};class Worker : public IWorker {
public:void work() override {// 工作}void eat() override {// 吃饭}
};class Robot : public IWorker {
public:void work() override {// 工作}void eat() override {// 机器人不吃饭throw std::logic_error("Robots don't eat");}
};// 应用ISP后
class IWorkable {
public:virtual void work() = 0;
};class IFeedable {
public:virtual void eat() = 0;
};class Worker : public IWorkable, public IFeedable {
public:void work() override {// 工作}void eat() override {// 吃饭}
};class Robot : public IWorkable {
public:void work() override {// 工作}
};

6. 迪米特法则 (Law of Demeter, LoD)

- 一个对象应该对其他对象有最少的了解,即“只和你的直接朋友通信”。可以降低对象之间的耦合,提高系统的模块化,但可能增加系统的消息传递复杂度。

class Engine {
public:void start() {// 启动引擎}
};class Car {
public:Engine* getEngine() {return &engine;}
private:Engine engine;
};class Driver {
public:void startCar(Car& car) {car.getEngine()->start();}
};// 应用LoD后
class Engine {
public:void start() {// 启动引擎}
};class Car {
public:void start() {engine.start();}
private:Engine engine;
};class Driver {
public:void startCar(Car& car) {car.start();}
};

7. 合成复用原则 (Composite Reuse Principle, CRP)

- 尽量使用对象组合,而不是继承来达到复用的目的。这样可以减少类之间的耦合,提高系统的灵活性,但可能需要更多的对象管理代码,增加系统的复杂度。

class Engine {
public:void start() {// 启动引擎}
};class ElectricEngine : public Engine {
public:void start() override {// 启动电动引擎}
};class Car {
public:void start() {engine.start();}
private:Engine engine;
};// 应用CRP后
class Engine {
public:virtual void start() = 0;
};class GasEngine : public Engine {
public:void start() override {// 启动燃气引擎}
};class ElectricEngine : public Engine {
public:void start() override {// 启动电动引擎}
};class Car {
public:Car(Engine* engine) : engine(engine) {}void start() {engine->start();}
private:Engine* engine;
};

8. 最少知识原则 (Least Knowledge Principle, LKP)

- 一个对象应尽可能少地了解其他对象,以减少相互依赖。可以降低对象之间的耦合,提高系统的灵活性和可维护性,但也有可能需要引入更多的接口或中介,增加系统的复杂度。

class Engine {
public:void start() {// 启动引擎}
};class Transmission {
public:void shiftGear() {// 换挡}
};class Car {
public:Engine* getEngine() {return &engine;}Transmission* getTransmission() {return &transmission;}
private:Engine engine;Transmission transmission;
};class Driver {
public:void startCar(Car& car) {car.getEngine()->start();car.getTransmission()->shiftGear();}
};// 应用LKP后
class Engine {
public:void start() {// 启动引擎}
};class Transmission {
public:void shiftGear() {// 换挡}
};class Car {
public:void start() {engine.start();transmission.shiftGear();}
private:Engine engine;Transmission transmission;
};class Driver {
public:void startCar(Car& car) {car.start();}
};

C++中的23种设计模式

C++中的23种设计模式_c++设计模式-CSDN博客

相关文章:

C++中的八大设计原则

目录 摘要 C中的8大设计原则 1. 单一职责原则 (Single Responsibility Principle, SRP) 2. 开放封闭原则 (Open/Closed Principle, OCP) 3. 里氏替换原则 (Liskov Substitution Principle, LSP) 4. 依赖倒置原则 (Dependency Inversion Principle, DIP) 5. 接口隔离原则…...

2024广东省职业技能大赛云计算赛项实战——Minio服务搭建

Minio服务搭建 前言 这道题是比赛时考到的,没找到具体题目,但在公布的样题中找到了,虽然很短~ 使用提供的 OpenStack 云平台,申请一台云主机,使用提供的软件包安装部署 MINIO 服务并使用 systemctl 管理 Minio是一个…...

【考研408计算机组成原理】数值表示和运算之快速数值转换

苏泽 “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家 另外,利用了工作之余的一点点时间,整理了一套考研408的知识图谱, 我根据这一套知识图谱打造了这样一个408知识图谱问答系统 里面的每一…...

理解 JTBD 框架和EJ 理念:深挖以用户为中心的设计

在与用户的交流中,我们发现对用户需求的精准洞察普遍困扰着产品经理、设计、企划人员,因为当今消费者行为已经由单品消费转向场景消费,千人千面的个性化需求出现,消费者数据维度极大丰富,这对把握用户体验造成了很大挑…...

数据提取与治理:企业实现数据驱动决策的必经之路

数据提取与治理:企业实现数据驱动决策的必经之路 随着信息技术的迅猛发展,数据已经成为企业最宝贵的资产之一。然而,数据并非天生就具有价值,只有通过有效的提取和治理,才能转化为企业决策的有力支撑。本文将探讨数据…...

Avalonia:一个.NET跨平台UI框架

概述 Avalonia是一个强大的框架,使开发人员能够使用. NET创建跨平台应用程序。它使用自己的渲染引擎来绘制UI控件,确保在各种平台上保持一致的外观和行为,包括Windows,macOS,Linux,Android,iOS…...

海量数据处理——bitMap/BloomFilter、hash + 统计 + 堆/归并/快排

前言:海量数据处理是面试中一道常考的问题, 生活中也容易遇到这种问题。 通常就是有一个大文件, 让我们对这个文件进行一系列操作——找出现次数最多的数据、求交集、是否重复出现等等。 因为文件的内容太多, 我们的内存通常是放不…...

TrainingArguments、ModelArguments、DataArguments参数使用(@dataclass)

文章目录 前言一、@dataclass装饰器说明二、transformers.HfArgumentParser参数使用Demo三、field函数四、llava模型参数1、模型参数设置2、数据参数设置3、训练参数设置4、参数解析5、参数传递6、参数添加前言 理解llava相关参数传递方法,有利于我们对模型修改模块使用参数来…...

基于jeecgboot-vue3的Flowable流程-自定义业务表单处理(一)支持同一个业务多个关联流程的选择支持

因为这个项目license问题无法开源,更多技术支持与服务请加入我的知识星球。 这部分先讲讲支持自定义业务表单一个业务服务表单多个流程的支持处理 1、后端mapper部分 如下,修改selectSysCustomFormByServiceName为list对象,以便支持多个 &…...

解决数据丢失问题的MacOS 数据恢复方法

每个人都经历过 Mac 硬盘或 USB 驱动器、数码相机、SD/存储卡等数据丢失的情况。我们中的一些人可能认为已删除或格式化的数据将永远丢失,因此就此作罢。对于 macOS 用户来说,当文件被删除时,垃圾箱已被清空,他们可能不知道如何恢…...

[ARM-2D 专题]3. ##运算符

C语言的宏系统相当强大,它允许使用##符号来处理预处理期的文本替换。这种用法被称为标记连接(token pasting)操作,其结果是将两个标记紧紧地连接在一起,而省略掉它们之间的所有空格。在复杂的宏定义中,运用…...

基于语音识别的智能电子病历(五)电子病历编辑器

前言 首先我们要明确一个概念:很多电子病历的编辑器,在输入文字的地方,有个麦克风按钮,点击一下,可以进行录音,然后识别的文字会自动输入到电子病历中,这种方式其实不能称为“基于语音识别的智…...

云计算技术高速发展,优势凸显

云计算是一种分布式计算技术,其特点是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序,并通过多部服务器组成的系统进行处理和分析这些小程序,最后将结果返回给用户。它融合了分布式计算、效用计算、负载均衡、并行计算、网络存储…...

文本三剑客其二

文本三剑客其二 sed和awk grep就是查找文本当中的内容,扩展正则表达式。 sed 对文本内容进行增删改查 sed是一种流编辑器,一次处理一行内容。 如果只是展示,会放在缓冲区(模式空间),展示结束之后&…...

【达梦数据库】typeorm+node.js+达梦数据库返回自增列值

1.配置环境,下载依赖包 typeorm init --name test22 --database mysql typeorm-dm,uuid,typeorm2,修改连接信息 修改src/ data-source.ts 文件 连接dm,可参考刚刚安装typeorm-dm 模块中的 README.md 3.修改自增信息 /* 修改前*/PrimaryGen…...

【ARMv8/ARMv9 硬件加速系列 2.1 -- ARM NEON 向量寄存器单个元素赋值】

文章目录 NEON 向量寄存器单个元素赋值对 v0.4s中的一个元素赋值对 v1.16b 中的一个元素赋值MOVI (Move Immediate)NEON 向量寄存器单个元素赋值 在ARMv8架构中,你可以使用特定的指令来对v0.4s和v1.16b中的单个元素赋值。这通常通过使用MOV(Move)指令的变种实现,具体取决于…...

GD32学习

参考视频13.立创开发板GD32教程:串口配置_哔哩哔哩_bilibili 固件库跟用户手册基本上差不多,只不过用用户手册编写程序的话会更加的底层,固件库的话就是把一些函数封装起来,用的时候拿过来即可,目前我还没有找到固件库…...

LangChain:如何高效管理 LLM 聊天历史记录?

LangChain 团队发布了一篇关于使用 Dragonfly DB 来有效管理 LangChain 应用程序聊天历史记录的教程。 该教程旨在解决用户在使用 LangChain 应用程序时普遍遇到的一个问题:如何高效地管理聊天历史记录。 LangChain 团队在推文中强调了 Dragonfly DB 在管理聊天历…...

【React】useState 更新延迟的原因是什么,怎么解决?

useState 更新延迟的原因 异步更新:React 中的 useState 更新是异步的,这意味着当你调用更新函数(如 setData)时,React 并不立即同步更新状态,而是将其放入一个待处理的队列中,稍后在适当的时候(如在下一次渲染之前)进行处理。因此,如果你尝试在调用更新函数后立即读…...

非关系型数据库NoSQL数据层解决方案 之 redis springboot整合与读写操作 2024详解以及window版redis5.0.14下载百度网盘

redis下载安装以及基本使用 下载地址 链接:百度网盘 请输入提取码 提取码:0410 一个名对应一个数值 内存级 在内存里进行操作 准备启动 我们现在就有一个redis客户端的服务器了 我们再启动一个cmd 操作redis数据库 redis里面的基本数据类型有五种 …...

jigdo无法下载的文件

问题描述 用jigdo下载Debian的iso镜像,剩下最后一个文件下载不了,提示信息: Found 0 of the 1 files required by the template Copied input files to temporary file debian-12.5.0-amd64-DLBD-2.iso.tmp - repeat command and supply mo…...

C#面:C# 类的执行顺序?

C# 类的执行顺序可以分为以下几个步骤: 静态字段初始化:在类的第一次使用之前,静态字段会被初始化。静态字段的初始化顺序是按照它们在代码中的声明顺序进行的。静态构造函数:如果类中定义了静态构造函数,它会在类的第…...

昇思25天学习打卡营第3天|数据集Dataset

一、简介: 数据是深度学习的基础,高质量的数据输入将在整个深度神经网络中起到积极作用。有一种说法是模型最终训练的结果,10%受到算法影响,剩下的90%都是由训练的数据质量决定。(doge) MindSpore提供基于…...

SpringCloud 服务调用 spring-cloud-starter-openfeign

在Spring Cloud中,spring-cloud-starter-openfeign 是一个用于声明式Web服务客户端(例如REST客户端)的启动器。它使得在Spring Cloud应用中调用其他HTTP服务变得非常简单,只需创建一个接口并使用注解来定义服务调用的细节。 以下…...

基于Elementui组件,在vue中实现多种省市区前端静态JSON数据展示并支持与后端交互功能,提供后端名称label和id

基于Elementui组件,在vue中实现多种省市区前端静态数据(本地JSON数据)展示并支持与后端交互功能,提供后端名称label和id 话不多说,先上图 1.支持传递给后端选中省市区的id和名称,示例非常完整&#xff0c…...

基于DPU的云原生裸金属网络解决方案

1. 方案背景和挑战 裸金属服务器是云上资源的重要部分,其网络需要与云上的虚拟机和容器互在同一个VPC下,并且能够像容器和虚拟机一样使用云的网络功能和能力。 传统的裸金属服务器使用开源的 OpenStack Ironic 组件,配合 OpenStack Neutron…...

pip install镜像源(更新和换源)

pip install镜像源(更新和换源) 1.pip安装依赖包默认访问的源: 因为服务器架设在国外的缘故,很多时候不好用网速不行,这时候就需要选择国内的一些安装源安装相应的包 https://pypi.Python.org/simple/2.设置默认源 …...

基础语法——组合与继承

继承 定义派生类,即继承的一般语法结构如下 class 派生类名 : [继承方式] 基类名 { }; 例如 class Point{int x, y; public:Point(int a0, int b0): x(a), y(b){}virtual double area() {return 0.0; };virtual double volume() { return 0.0; } }; class Circl…...

openGauss开发者大会、华为云HDC大会举行; PostgreSQL中国技术大会7月杭州开启

重要更新 1. openGauss Developer Day本周五于北京举行,大会聚集了相关行业专家、用户、伙伴和开发者,分享给予openGauss的联合创新成果和实践案例。([2] ) ;华为云 HDC 2024本周五于东莞松山湖举行,主题演讲主要覆盖鸿蒙、AI ([3…...

编译报错:No rule to make target xx/libcam.halmemory_intermediates/export_includes

问题现象: make: *** No rule to make target ‘out/target/product/testdd6737m_35g_m0/obj/STATIC_LIBRARIES/libcam.halmemory_intermediates/export_includes’, needed by ‘out/target/product/testdd6737m_35g_m0/obj/SHARED_LIBRARIES/libcam_platform_inte…...

wordpress首页跳转/seo平台

构建编译项目不需要安装CMake,MinGW等额外工具。只需要Android NDK和OpenCV源码。在WIN10上使用cmd窗口命令编译OpenCV步骤,操作版本为4.0.1:在OpenCV根目录下面新建一个文件夹,比如叫做build_cmd。因为OpenCV要求CMAKE_BINARY_DI…...

两学一做网站安徽省/百度学术论文查重免费

软件的本质:产品和产品交付载体。 软件与硬件的不同: 1)软件是设计开发,而非生产制造。 2)软件不会磨损,但会退化。退化的原因是变更,不断的变更可能会引入新的错误,使得失效律越来越…...

备案网站应用服务/seo专业培训班

//这是一个在参数指定文件中连续写入当前时间的应用//文件以1秒为时间间隔,将当前的时间写入文件,然后回车换行//这是一个使用lseek在一个文件中连续写入字符串的应用#include #include #include #include int main(int argc,char *argv[]){int temp,see…...

怎样进行网站备案/附近电脑培训学校

1、Linux cp命令 拷贝文件 https://blog.csdn.net/sqbzo/article/details/9000027 2、linux复制指定目录下的全部文件到另一个目录中,linux cp 文件夹 http://www.cnblogs.com/zdz8207/p/linux-cp-dir.html...

简约大气网站欣赏/如何让新网站被收录

cookie,localStorage,sessionStorage 相同点:cookie,localStorage,sessionStorage都是在客户端保存数据的,存储数据的类型:都是字符串。 不同点: 1、生命周期: 1&…...

番禺网站建设公司排名/北京推广平台

fps游戏在上一篇文章中,我们创建了一个以恒定速度和恒定(或多或少)FPS运行的游戏循环。 我们如何测量呢? 检查新的MainThread.java类。 package net.obviam.droidz;import java.text.DecimalFormat;import android.graphics.Canvas; import android.uti…...