高层模块不应该依赖底层模块,两都都应该依赖抽象
一个三层的Demo
/// <summary>
/// 人员实体类
/// </summary>
class Person
{public int ID { get; set; }public string Name { get; set; }public bool Sex { get; set; }
}
/// <summary>
/// 表示层
/// </summary>
class UI
{public void Main(){ShowPerson();} public static void ShowPerson(){Console.WriteLine("输入要查询的人员ID");var id = int.Parse(Console.ReadLine());var bll = new BLL();var person = bll.FindPerson(id);Console.WriteLine($"ID:{person.ID},Name:{person.Name},Sex:{(person.Sex ? "男" : "女")}");}
}
/// <summary>
/// 业务逻辑层
/// </summary>
class BLL
{public Person FindPerson(int id){var dal = new DAL();return dal.QueryPersonByID(id);}
}
/// <summary>
/// 数据访问层
/// </summary>
class DAL
{public Person QueryPersonByID(int id){return new Person { ID = id, Name = "张三丰收", Sex = true };}
}
高层模块指的是调用方:
UI类ShowPerson方法中bll.FindPerson
BLL类FindPerson方法中dal.QueryPersonByID
底层模块指的是实现模块:
BLL类FindPerson()方法
DAL类QueryPersonByID()方法
这是直接用法,为了降低耦合,响应需求变化,要把这种强依赖切降低,遵照“依赖倒置”,增加抽象层,用抽像层隔离高层和底层模块,本代码段中用一个ObjectHub来集中管理实例化过程,如下代码:
#region 实体类/// <summary>/// 人员实体类/// </summary>class Person{public int ID { get; set; }public string Name { get; set; }public bool Sex { get; set; }}#endregion#region 对象仓库/// <summary>/// 对象仓库/// </summary>class ObjectHub{public static Dictionary<string, object> Container { get; private set; }static ObjectHub(){//通过这里来解耦Container = new Dictionary<string, object>{{ nameof(IDAL), new DAL() },{ nameof(IBLL),new BLL() }};}}#endregion#region 表示/// <summary>/// 表示层/// </summary>class UI{static void Main(string[] args){var ui = new UI();ui.ShowPerson();}public void ShowPerson(){//依赖业务逻辑层接口var bll = ObjectHub.Container[nameof(IBLL)] as IBLL;Console.WriteLine("输入要查询的人员ID");var id = int.Parse(Console.ReadLine());var person = bll.FindPerson(id);Console.WriteLine($"ID:{person.ID},Name:{person.Name},Sex:{(person.Sex ? "男" : "女")}");}}#endregion#region 业务逻辑/// <summary>/// 业务逻辑层接口/// </summary>interface IBLL{Person FindPerson(int id);}/// <summary>/// 业务逻辑层/// </summary>class BLL : IBLL{public Person FindPerson(int id){//依赖业务逻辑层接口var dal = ObjectHub.Container[nameof(IDAL)] as IDAL;return dal.QueryPersonByID(id);}}#endregion#region 数据访问/// <summary>/// 数据访问层接口/// </summary>interface IDAL{Person QueryPersonByID(int id);}/// <summary>/// 数据访问层/// </summary>class DAL : IDAL{public Person QueryPersonByID(int id){return new Person { ID = id, Name = "张三丰收", Sex = true };}}#endregion
原来是高层模块依赖底层模块,现在依赖倒置,怎么倒置了呢?个人理解:高层和底层之间出现了一个抽像,高层依赖抽象,按理抽象依赖底层,但这里恰恰是底层和也依赖抽象,打破了一个依赖链,形成一个倒置。