2026/1/28 5:31:31
网站建设
项目流程
.net 企业网站源码,app开发设计,大数据营销论文,岳阳网站开发公司推荐前言#xff1a;在平时coding过程中#xff0c;大部分程序员可能把更多精力和时间花在功能的实现和完成上面#xff0c;对于代码的可读性、可读性及可扩展性没有过多的关注#xff0c;这可能会造成后期功能扩展困难、新人无法理解等问题。这里介绍一些软件代码设计原则在平时coding过程中大部分程序员可能把更多精力和时间花在功能的实现和完成上面对于代码的可读性、可读性及可扩展性没有过多的关注这可能会造成后期功能扩展困难、新人无法理解等问题。这里介绍一些软件代码设计原则帮助大家提升代码质量。目录一、SOLID软件设计原则二、单一职责原则Single Responsible Principle二、开闭原则Open Close Principle三、里氏替换原则Liskov Substitution Principle四、接口隔离原则Interface Segregation Principle五、依赖倒置原则Dependency Inversion Principle一、SOLID软件设计原则SOLID是面向对象软件设计中5个基础设计原则的简写由Robert C. Martin提出是设计模式的指导思想。这些原则包括单一职责原则、开闭原则、里氏替换原则、接口隔离原则、依赖倒置原则。下面章节分别展开介绍。二、单一职责原则Single Responsible Principle1定义一个类应当只做一件事情只有一个引起它变化的原因2思想避免一个类同时负责多个功能否则对一个功能的修改可能会影响到其他功能修改扩展成本增加。3示例反例一个UserManager类同时负责用户信息管理和用户日志记录如果日志的存储方式修改比如从本地文件改成数据库就需要修改这个类违反了单一职责。正例拆分为两个类// 只负责用户信息的管理 class UserManager { public: void addUser(const std::string username) { // 处理用户添加的逻辑 } void deleteUser(const std::string username) { // 处理用户删除的逻辑 } }; // 只负责用户相关的日志记录 class UserLogger { public: void logUserOperation(const std::string username, const std::string operation) { // 处理日志记录的逻辑 } };二、开闭原则Open Close Principle1定义软件模块类、函数等应该对扩展开放对修改关闭。2思想当需要新增功能时应当通过扩展已有代码模块来实现而不是在已有代码上直接修改、打补丁防止补丁上打补丁时间长了就难以维护了。3示例反例一个ShapeCalculator类计算不同图形的面积如果新增一种图形比如椭圆就需要修改类的代码// 反例新增图形需要修改这个类 class ShapeCalculator { public: double calculateArea(const std::string shapeType, double param1, double param2) { if (shapeType circle) { return M_PI * param1 * param1; } else if (shapeType rectangle) { return param1 * param2; } // 新增椭圆需要在这里加else if return 0; } };正例通过抽象类继承实现// 抽象的图形类 class Shape { public: virtual double calculateArea() const 0; virtual ~Shape() default; }; // 圆形类继承Shape class Circle : public Shape { private: double radius; public: Circle(double r) : radius(r) {} double calculateArea() const override { return M_PI * radius * radius; } }; // 矩形类继承Shape class Rectangle : public Shape { private: double width; double height; }; // 面积计算器只依赖抽象类新增图形不需要修改这个类 class ShapeCalculator { public: double calculateArea(const Shape shape) { return shape.calculateArea(); } };上述代码中出现了虚函数和抽象类的概念如需要可参考之前的文章C 虚函数 解析指南-CSDN博客三、里氏替换原则Liskov Substitution Principle1定义子类对象可以替换父类对象在程序中的所有使用场景且不会改变程序的正确性。2思想子类必须完全实现父类功能不能破坏父类的行为避免继承关系的滥用。3示例反例正方形继承矩形但是正方形的宽和高必须相等修改宽的时候高也会变化破坏了矩形的行为class Rectangle { protected: double width; double height; public: void setWidth(double w) { width w; } void setHeight(double h) { height h; } double getArea() { return width * height; } }; // 反例正方形继承矩形但是setWidth和setHeight的行为不符合父类的约定 class Square : public Rectangle { public: void setWidth(double w) override { width w; height w; } void setHeight(double h) override { width h; height h; } };正例重新设计继承关系使得正方形与矩形都继承抽象的Shape类。四、接口隔离原则Interface Segregation Principle1定义客户端不应当依赖它不需要的接口一个类对另一个类的依赖应当建立在最小接口上。2思想避免设计大而全的接口接口应当拆分多个小的高内聚、低耦合。3示例反例一个大的Worker接口包含了所有工作相关的方法但是不同的 worker 只需要其中一部分// 反例大而全的接口 class Worker { public: virtual void work() 0; virtual void eat() 0; virtual void sleep() 0; }; // 机器人只需要work但是必须实现eat和sleep class Robot : public Worker { public: void work() override { /* 工作逻辑 */ } void eat() override { /* 机器人不需要吃饭空实现 */ } void sleep() override { /* 机器人不需要睡觉空实现 */ } };正例拆分为小接口// 只包含工作的接口 class Workable { public: virtual void work() 0; virtual ~Workable() default; }; // 只包含休息相关的接口 class Restable { public: virtual void eat() 0; virtual void sleep() 0; virtual ~Restable() default; }; // 机器人只实现Workable接口 class Robot : public Workable { public: void work() override { /* 工作逻辑 */ } }; // 人类实现Workable和Restable接口 class HumanWorker : public Workable, public Restable { public: void work() override { /* 工作逻辑 */ } void eat() override { /* 吃饭逻辑 */ } void sleep() override { /* 睡觉逻辑 */ } };五、依赖倒置原则Dependency Inversion Principle1定义上层模块不应当依赖底层模块抽象不应当依赖细节细节应当依赖抽象。2思想通过抽象抽象类或接口实现上层与底层解耦使得模块之间依赖关系倒置提高灵活性。3示例反例上层模块ReportGenerator直接依赖底层模块MySQLDatabase如果需要切换数据库比如改成PostgreSQL就需要修改ReportGenerator// 反例上层依赖底层的具体实现 class MySQLDatabase { public: std::string getData() { return 从MySQL获取的数据; } }; class ReportGenerator { private: MySQLDatabase db; public: std::string generateReport() { return 报告内容 db.getData(); } };正例通过抽象接口解耦// 抽象的数据库接口 class Database { public: virtual std::string getData() const 0; virtual ~Database() default; }; // MySQL的具体实现依赖抽象接口 class MySQLDatabase : public Database { public: std::string getData() const override { return 从MySQL获取的数据; } }; // PostgreSQL的具体实现依赖抽象接口 class PostgreSQLDatabase : public Database { public: std::string getData() const override { return 从PostgreSQL获取的数据; } }; // 高层模块依赖抽象接口而不是具体实现 class ReportGenerator { private: const Database db; public: // 通过构造函数注入依赖 ReportGenerator(const Database database) : db(database) {} std::string generateReport() { return 报告内容 db.getData(); } };结束语一般这5种原则不会孤立存在通常两三个会结合在一起使用。读者可参考进行理解消化最终目的是应用于实际项目中实现代码质量显著提升。