.依赖倒置原则
- 定义
高层模块不应该依赖于底层模块,而应该依赖于抽象。抽象不应依赖于细节,细节应依赖于抽象。 - 解决的问题
类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。因此我们需要将依赖的方向进行重新规划,像下面这样:
我们将接口与实现相分离,应用与细节相分离,接口层提供我们业务层所需要的接口方法,实现层对接口的具体方法进行实现,高层业务逻辑不关心接口实现的具体细节,它只对接口进行调用,从而降低了类之间的耦合性,增加了代码的可读性,降低了后续维护的成本。
实例:
定义一个武汉店类,该类有个sell()方法,访问该方法可以显示周黑鸭
class wuhanshop
{
public:
void sell()
{
cout << "zhouheiya" << endl;
}
};
定义一个顾客类,顾客类中有gouwu()方法,通过往该方法中传具体的商店来进行购物
class guke
{
public:
void gouwu(wuhanshop ws)
{
ws.sell();
}
};
下面开始购物
void main()
{
guke mike;
wuhanshop ws;
mike.gouwu(ws);
}
如果此时顾客mike想去其他商店,比如福建商店进行购物买烤老鼠
class fujianshop
{
public:
void sell()
{
cout << "kaolaoshu" << endl;
}
};
此时main函数换成
void main()
{
guke mike;
fujianshop fs;
mike.gouwu(fs);
}
此时guke类也要修改
class guke
{
public:
void gouwu(fujianshop fs)
{
fs.sell();
}
};
假如以后需求换成湖南店呢?换成上海店呢?还要不断地修改 guke类,这显然不是好的设计。原因就是 guke类与 具体的shop类 之间的耦合性太高了,必须降低他们之间的耦合度才行。耦合度高的影响就是一旦商店改变,顾客就需要改变。
强耦合关系:任意一方的改变都将导致双方发生改变
因此我们在guke类与具体的shop类中提供一个抽象类shop
#include<iostream>
using namespace std;
class shop
{
public:
virtual void sell() = 0;
};
class guke
{
public:
void gouwu(shop* shop)
{
shop->sell();
}
};
class wuhanshop:public shop
{
public:
void sell()
{
cout << "zhouheiya" << endl;
}
};
class fujianshop :public shop
{
public:
void sell()
{
cout << "kaolaoshu" << endl;
}
};
void main()
{
guke mike;
wuhanshop ws;
fujianshop fs;
mike.gouwu(&ws);
mike.gouwu(&fs);
}
将guke类中的参数设为指向抽象类shop的指针,具体的商店继承该抽象shop,因为父类指针可以指向子类对象,因此在购物时将具体商店子类对象的地址传进去,而不需要改变guke类
细节指具体的实现类,抽象指接口或者抽象类
在软件设计中,具体类会随着业务的变化有很多种,beijing,guangzhou…各种商店类,然而其抽象类shop始终是稳定的。以抽象为基础搭建起来的架构要比以细节为基础搭建起来的架构要稳定的多。使用抽象类的目的是制定好规范和契约,将展现细节的任务交给他们的实现类。