2023年8月30日,周三上午
目录
依赖倒转原则(Dependency Inversion Principle,DIP)是面向对象设计中的一个基本原则。
高层模块不应该依赖低层模块,两者都应该依赖其抽象。
也就是说:
这违反了依赖倒转原则,因为高层用户模块直接依赖了低层数据库模块。
用户模块 -> 直接依赖数据库模块
- 依赖 实现
- 用户模块 -----> 接口/抽象基类<-----数据库模块
这样一来,用户模块与数据库模块的依赖关系就通过抽象进行了解耦。如果需要替换数据库,只需要修改数据库模块的实现,不影响用户模块。
总之,依赖倒转原则通过抽象层解耦高低层模块的依赖关系,提高了模块的独立性、可扩展性和可维护性。
这里用一个简单的代码例子来说明依赖倒转原则。
- 依赖 实现
- UserModule -----> 抽象类IDataBase<-----MysqlDatabase
首先定义一个数据库操作的接口:
- // 抽象接口
- class IDatabase {
- public:
- virtual void Insert(const string& data) = 0;
- virtual void Select() = 0;
- };
然后实现这个接口的具体数据库类:
- // 具体实现
- class MysqlDatabase : public IDatabase{
- public:
- void Insert(const string& data) override {
- // 具体插入逻辑
- }
-
- void Select() override {
- // 具体查询逻辑
- }
- };
用户模块只依赖接口,不依赖具体实现:
- // 用户模块
- class UserModule {
- private:
- IDatabase* db;
-
- public:
- UserModule(IDatabase* db) : db(db) {}
-
- void Run() {
- // ...
- db->Insert("some data");
- db->Select();
- }
- };
在主函数中:
- int main() {
-
- MysqlDatabase mysql;
- UserModule user(&mysql);
-
- user.Run();
-
- return 0;
- }
在这个程序里:
如果需要替换数据库,只需要修改MysqlDatabase实现,而不影响用户模块。这就是依赖倒转原则的实现。
在windows平台上用这套
- 依赖 实现
- DrawingProgram -----> 抽象类IShape<-----RectangleOnWindows
在Linux平台上用这套
- 依赖 实现
- DrawingProgram -----> 抽象类IShape<-----RectangleOnLinux
- #include
-
- class IShape {
- public:
- virtual void draw() = 0;
- };
-
- //在windows平台上画矩形
- class RectangleOnWindows : public IShape {
- public:
- void draw() override {
- std::cout << "在Windows上画矩形" << std::endl;
- std::cout << "先画左边和右边,再画上边和下边" << std::endl;
- }
- };
-
- //在Linux平台上画矩形
- class RectangleOnLinux : public IShape {
- public:
- void draw() override {
- std::cout << "在Linux上画矩形" << std::endl;
- std::cout << "先画上边和左边,再画下边和右边" << std::endl;
- }
- };
-
- class DrawingProgram {
- private:
- IShape* shape;
-
- public:
- DrawingProgram(IShape* shape) {
- this->shape = shape;
- }
-
- void run() {
- shape->draw();
- }
- };
- int main() {
-
- //在Windows平台上用这一套
- RectangleOnWindows ROW;
- DrawingProgram program(&ROW);
- program.run();
-
- //在Linux平台上用这一套
- // RectangleOnLinux ROL;
- // DrawingProgram program(&ROL);
- // program.run();
-
- return 0;
- }
-
这这个程序中:
如果需要添加新的形状,只需要实现形状接口,不影响绘图程序。这就是一个完整的依赖倒转原则示例。
电脑中的主板就是最好的一个依赖倒转原则例子,
在主板上有非常多的硬件接口,用来安装内存、硬盘、电源等等,
这些硬件接口就相当于抽象类,
正是因为有了接口,才能在一块主板上安装不同品牌、不同厂商生产的内存条、硬盘、电源等等。
如果主板上没有这些硬件接口,而是直接让主板与某个品牌的内存条连接,
那么当这个内存条坏了,你就只能买这个品牌的内存条,用其他品牌的没用,
因为这个主板是针对这个品牌的内存条设计的,没办法做到抽象,也就只能用这个品牌的。