首页 > 编程笔记 > C++笔记 阅读:18

依赖倒置原则(附带C++实例)

依赖倒置原则是 SOLID 设计原则中的第五个原则,它强调“高层模块不应依赖于低层模块,两者都应依赖于抽象;抽象不应依赖于细节,细节应依赖于抽象”。DIP 主张在软件组件之间建立稳定的抽象,使得高层(策略性和复杂的决策逻辑)和低层(具体的操作细节)的模块都依赖于这些抽象。

这个原则帮助我们避免高层模块对低层模块的直接依赖,如实现细节或具体操作,从而使得改变一个系统的低层实现不会影响到高层模块。

实现依赖倒置原则的方法如下:
依赖倒置原则具有以下优势:
实现依赖倒置原则的挑战如下:

实例:重构不遵循DIP的C++设计

接下来,将通过一个具体的 C++ 示例来展示依赖倒置原则的实现。这个示例将说明如何在实际的软件项目中设计模块,以使它们依赖于抽象而不是具体的实现,从而提高代码的可维护性和灵活性。

1) 初始设计

假设有一个应用程序,它需要记录信息。最初的设计直接依赖于一个具体的日志记录类,这意味着高层模块(如业务逻辑类)直接依赖于低层模块(如文件日志记录器)。
#include <iostream>
#include <fstream>
#include <string>
// 低层模块
class FileLogger {
public:
    void logMessage(const std::string& message) {
        std::ofstream logFile("log.txt", std::ios::app);
        logFile << message << std::endl;
        logFile.close();
    }
};
// 高层模块
class Application {
private:
    FileLogger logger;
public:
    void process() {
        // 业务逻辑
        logger.logMessage("Process started.");
        // 更多业务逻辑...
        logger.logMessage("Process finished.");
    }
};

2) 重构设计

为了遵循依赖倒置原则,首先定义一个抽象的日志接口,然后让高层模块依赖于这个接口,而不是具体的日志记录实现。这样,不同的日志记录方式(如文件记录、数据库记录或网络日志记录)可以通过不同的实现类提供服务,而无须修改高层模块。
#include <iostream>
#include <fstream>
#include <string>
// 抽象接口
class ILogger {
public:
    virtual ~ILogger() {}
    virtual void logMessage(const std::string& message) = 0;
};
// 具体实现:文件日志记录
class FileLogger : public ILogger {
public:
    void logMessage(const std::string& message) override {
        std::ofstream logFile("log.txt", std::ios::app);
        logFile << message << std::endl;
        logFile.close();
    }
};
// 高层模块
class Application {
private:
    ILogger& logger;
public:
    Application(ILogger& logger) : logger(logger) {}
    void process() {
        logger.logMessage("Process started.");
        // 更多业务逻辑...
        logger.logMessage("Process finished.");
    }
};
// 在客户端代码中使用
int main() {
    FileLogger fileLogger;
    Application app(fileLogger);
    app.process();
    return 0;
}
通过这种重构,Application 类不再直接依赖于 FileLogger,而是依赖于 ILogger 接口。这样,日志记录的具体实现方式可以灵活替换,而不影响 Application 类的实现。例如,如果未来需要将日志记录到云服务而非文件,我们只需提供一个新的 ILogger 实现即可。

这个示例展示了依赖倒置原则在实际中的应用,即通过抽象化依赖关系来提高软件模块的灵活性和可维护性。这种设计允许高层模块和低层模块独立于具体实现进行开发和维护,有效地解耦了系统的各个部分。

在大多数情况下,依赖倒置原则是一种非常有效的设计策略,特别是在需要保持高度灵活性和可扩展性的大型软件项目中。

然而,也存在一些特定场景,在其中严格遵循依赖倒置原则可能不是最优选择:

相关文章