一、简介
1、IOC核心理论来源DIP
DIP全称是Dependence Inversion Principle,中文叫依赖倒置原则。这是面向对象程序设计六大原则之一。
它的原则讲的是面向对象语言程序设计时,高层模块不要直接依赖于低层模块,二者应该通过抽象来依赖而不是依赖于细节。依赖细节,会导致低层的变化影响高层。依赖抽象, 低层的变化就不会影响高层,保持稳定,可扩展。对扩展开放,对修改封闭!这就是IOC的核心理论根基。
2、为什么依赖细节会导致底层的变化影响高层呢?
拿我们的三层架构来说,如下图,IOCTest是控制台程序,引用Dal和Bll层,Bll引用Dal层。

program.cs代码如下
UserSqlServerDal userDal = new UserSqlServerDal(); UserBll userBll = new UserBll(userDal); userBll.Login(1);
userBll的代码如下
public class UserBll
{
private UserSqlServerDal UserSqlServerDal { get; set; }
public UserBll(UserSqlServerDal userSqlServerDal)
{
UserSqlServerDal= userSqlServerDal;
}
public bool Login(int id)
{
object obj= UserSqlServerDal.Find(id);
return true;
}
}
UserSqlServerDal的代码如下
public class UserSqlServerDal
{
public object Find(int id)
{
return null;
}
}
如上代码,bll层引用了dal层的细节,console引用了bll的 细节。什么时候会造成下层的改动会引起上层的变更呢?
当我想切换数据库的时候,比如不用现在的sqlserver了,想换成mysql。那么这个时候就必须新增一个UserMysqlDal的dal类。然后bll层和console层的UserSqlServerDal都需要换成UserMysqlDal类。
public class UserBll
{
// private UserSqlServerDal UserSqlServerDal { get; set; }
// public UserBll(UserSqlServerDal userSqlServerDal)
// {
// UserSqlServerDal= userSqlServerDal;
// }
//public bool Login(int id)
//{
// object obj = UserSqlServerDal.Find(id);
// return true;
//}
private UserMySqlDal UserMySqlDal { get; set; }
public UserBll(UserMySqlDal userMySqlDal)
{
UserMySqlDal = userMySqlDal;
}
public bool Login(int id)
{
object obj= UserMySqlDal.Find(id);
return true;
}
}
//UserSqlServerDal userDal = new UserSqlServerDal(); UserMySqlDal userDal = new UserMySqlDal(); UserBll userBll = new UserBll(userDal); userBll.Login(1);
那如果需要兼容oracle,sqlLite等其他数据库的话,那bll和ui层不是要写一堆相同作用的代码?可以看的出来这种代码后期维护起来可真要命。所以不能依赖细节,而应该依赖抽象。下面我们对bll层和dal层进行解耦,使它们之间依赖抽象。新建一个Dal的接口层,让所有的具体Dal类继承这个接口。删除bll对dal的依赖引用。
namespace Test.IDal
{
public interface IUserDal
{
object Find(int id);
}
}
public class UserMySqlDal:IUserDal public class UserSqlServerDal:IUserDal
public class UserBll
{
private IUserDal UserDal { get; set; }
public UserBll(IUserDal userDal)
{
UserDal = userDal;
}
public bool Login(int id)
{
object obj= UserDal.Find(id);
return true;
}
}
IUserDal userDal = new UserMySqlDal(); UserBll userBll = new UserBll(userDal); userBll.Login(1);
这样,不管你ui层的userDal是mysql的实例还是sqlserver的实例,bll层都以统一的抽象来接受,下次更换mongodb的dal就不再需要修改userBll的代码了。
上面的ui层中,是不是还有new UserMysqlDal()和new UserBll的细节依赖,可以看到ui层都是在做实例化吧,这些实例化的过程就可以统一交给一个模块来做这个事情。
新建一个IBll层用来解耦UI和BLL层。
新建一个Common层来放Factory类专门来实现实例化类,引用IBLL,BLL,IDAL,DAL四个项目。
public class Factory
{
public static IUserDal CreateDal()
{
return new UserMySqlDal();
}
public static IUserBll CreateBll(IUserDal dal)
{
return new UserBll(dal);
}
}
删除UI层对BLL和DAL项目的引用。修改相关代码
IUserDal userDal = Factory.CreateDal(); IUserBll userBll = Factory.CreateBll(userDal); userBll.Login(1);
这样就让UI,BLL,DAL都依赖于抽象了。好处显然易见,只需要修改factory这个第三方库,就能完成数据库的切换了。改中间层的花销要比改上下层的风险要低得多。
原创文章,作者:kirin,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/268091.html