<一>IOC的核心理论来源DIP

一、简介

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这个第三方库,就能完成数据库的切换了。改中间层的花销要比改上下层的风险要低得多。

 

posted @ 2022-06-17 01:46  许轩霖  阅读(128)  评论(0编辑  收藏  举报