从前有一个这样的业务
@H_404_11@代码编号01 需求:在MSsqlServer数据库中添加订单信息
public class MSsqlServer
{
public void Insert(){...}
}
setp 2 构建订单服务,向MSsqlServer环境添加数据
public class OrderService
{
private MSsqlServer _mssqlServer;
public Order(MSsqlServer mssqlServer)
{
_mssqlServer = mssqlServer;
}
public void Add()
{
_mssqlServer.Insert();
}
}
setp 3 整体贯通,实现需求
static void Main()
{
var mssqlServer= new MSsqlServer();
var orderService = new OrderService(mssqlServer);
orderService.Insert();
}
一个呆萌的员工是这样扩展的
@H_404_11@代码编号02 需求变更:改用MysqL存储订单信息
public class MysqL
{
public void Insert(){...}
}
public class OrderService
{
private MSsqlServer _mssqlServer;
private MysqL _MysqL;
public Order(MSsqlServer mssqlServer)
{
_mssqlServer = mssqlServer;
}
public Order(MysqL MysqL)
{
_MysqL = MysqL;
}
public void Add()
{
_mssqlServer.Insert();
}
public void AddByMysqL()
{
_MysqL .Insert();
}
}
setp 3 整体贯通,实现需求
static void Main()
{
var MysqL= new MysqL();
var orderService = new OrderService(MysqL);
orderService.InsertByMysqL();
}
一个潜力的员工是这样扩展的
@H_404_11@代码编号03 需求变更:改用MysqL存储订单信息
setp 1 构建数据库访问接口
public interface IDataAccess
{
void Insert();
}
setp 2 实现MysqL环境
public class MysqLDataAccess : IDataAccess
{
public void Insert(){...}
}
setp 3 改造MSsqlServer环境
public class MSsqlServerDataAccess : IDataAccess
{
public void Insert(){...}
}
setp 4 改造订单服务,向IDataAccess环境添加数据
public class OrderService
{
private IDataAccess _dataAccess;
public Order(IDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
public void Add()
{
_dataAccess .Insert();
}
}
setp 5 整体贯通,实现需求
static void Main()
{
var MysqL= new MysqLDataAccess();
var orderService = new OrderService(MysqL);
orderService.Insert();
}
Leader是这样评价的
首先,02和03两段代码都能实现新的需求。
其次,03的代码比02的代码,更加的干净整洁。尤其是在OrderService中。
第三,02的每一次扩展,涉及到每个部分,包括新的实现方式、OrderService和贯通的部分。但03的每一次扩展,OrderService部分不需要改变。新增或是修改,改变了现有的其他模块,就有可能出现Bug,如果能尽可能的不改变一些模块,系统会变的更柔韧。
第四,如果需求要求使用DB2或Oracle来存储订单信息。03代码的实现,毫无疑问的更加容易实现,系统做到了好的扩展性。
第五,如果需求要求使用DB2或Oracle来存储订单信息。03代码的实现,毫无疑问更加简单,也意味着系统更加高效。
依赖倒置设计原则DIP的诞生
总结:03的实现方式带来了种种好处。因为OrderService使用的是存储的接口,不需要关心是使用哪种存储的实现方式。OrderService通过IDataAccess接口来耦合具体的实现,不需要耦合MSsqlServer还是MysqL,由一种强耦合变成了弱耦合,耦合度降低。
如果把最终使用接口的模块OrderService定义为高层模块,把提供服务实现手段的定义为底层模块,总结出:
高层模块需要其他低层模块什么功能,把需求抽象为一个低层模块的接口
各种低层模块的实现按着这个接口去实现
前辈大牛将这句话精炼为
@H_404_11@这就是依赖倒置设计原则DIP的诞生
生活中的应用
插头标准规定三插头的每个插头的宽度、高度、每两个插头间的距离等标准。插座的设计只要能满足三插头的标准,其他电器的三插头按照标准去实现,这样不管是电视、冰箱还是笔记本的插头,都可以使用这个插座。
反之插头也不需要关心用的插座是公牛还是红牛的。
ATM机的银行卡插槽只要设计满足于银联卡,就不需要关心取款人用的是工行卡还是农行卡。
USB的接口标准统一后,笔记本上的USB插口可以使用鼠标、键盘、U盘、硬盘。