首页 > 编程语言 >C++中的八大设计原则

C++中的八大设计原则

时间:2024-06-23 14:00:11浏览次数:3  
标签:std 八大 string 原则 void C++ public start class

目录

摘要

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博客

标签:std,八大,string,原则,void,C++,public,start,class
From: https://blog.csdn.net/GOLOJO/article/details/139737260

相关文章

  • C++U7-10-最小生成树
    本节课作业讲解视频:链接:https://pan.baidu.com/s/1lLlmhShdat9HuJWx7Rp_tA?pwd=0000提取码:0000  最小生成树是一种在无向图中寻找特定结构的算法结果,它具有多种实际应用。以下是关于最小生成树的一些主要应用:网络布局问题:在一个连通加权无向图中,最小生成树算法可以帮......
  • C++面向对象多级菜单向Arduino的移植
    前段时间写了一篇文章《C++面向对象语言自制多级菜单》,文中指出了可以将HeleMenu库进行移植,现已完成技术思路,特此记录。一、特性基本与上一篇文章指出的一致,只是将菜单显示和响应函数合二为一二、代码实现基本与上一篇文章指出的一致,只是考虑到右值和左值的问题,将形参改为了co......
  • C++ 智能指针
     问题引入intfunc1(intx){ inty=10; int*tmp=(int*)malloc(sizeof(int)*2); if(x==0) throw"func1_error"; else returnx+y; free(tmp);//抛异常造成异常安全问题,无法释放造成内存泄漏,}intmain(){ try{inta=func1(0);} catch(constc......
  • C++入门 vector深度剖析及模拟实现
    目录vector析构函数模拟实现vector赋值拷贝模拟实现vector拷贝构造模拟实现vector构造函数模拟实现类模板的成员函数n个val构造单参数和多参数对象隐式类型转换使用memcpy拷贝问题在上两篇有关vector的模拟实现中,还有构造,拷贝构造,赋值拷贝以及析构函数没有实现,本篇主......
  • SOLID原则笔记
    单一职责原则开闭原则里式替换(LSP)原则接口隔离原则如何理解“接口隔离原则”?接口隔离原则的英文翻译是“InterfaceSegregationPrinciple”,缩写为ISP。RobertMartin在SOLID原则中是这样定义它的:“Clientsshouldnotbeforcedtodependuponinterfacesthatthey......
  • C++ 20新特性之改进的位操作
    ......
  • 【小沐学GIS】Google的kml文件的读写(C++、Python)
    文章目录1、简介1.1kml简介1.2功能点1.2.1地标1.2.2地面叠加层1.2.3路径1.2.4多边形2、下载和编译3、C++测试4、Python测试4.1安装库4.2测试14.2测试24.3测试3结语1、简介https://developers.google.cn/kml/documentation/kmzarchives?hl=zh-cn1.1kml......
  • C++ 结构体对齐详解
    目录前言一、为什么要对结构体进行对齐操作?二、基本概念三、对齐规则四、示例讲解1.简单的变量对齐2.结构体包含有结构体的对齐结构体成员详细解析五、使用指令改变对齐方式__attribute__((packed))#pragmapack(push,n)#pragmapack(pop)六、总结前......
  • 2024年华为OD机试真题-生成哈夫曼树-(C++/Java/python)-OD统一考试(C卷D卷)
    题目描述给定长度为n的无序的数字数组,每个数字代表二叉树的叶子节点的权值,数字数组的值均大于等于1。请完成一个函数,根据输入的数字数组,生成哈夫曼树,并将哈夫曼树按照中序遍历输出。为了保证输出的二叉树中序遍历结果统一,增加以下限制:二叉树节点中,左节点权值小于右节点......
  • 设计模式六大原则(一)---单一职责原则
    单一职责原则(SingleResponsibilityPrinciple,SRP)是面向对象设计中的一个原则,它要求一个类或模块应该有且只有一个引起它变化的原因。单一职责原则主要解决的问题是类的职责过于复杂,即一个类承担了过多的责任。当一个类具有多个职责时,任何一个职责的变化都可能影响到其他职责,导致......