一. 依赖倒置原则
1. 定义
高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
通俗的来说:就是面向接口(或抽象类)编程。
补充说明:
(1). 依赖倒置原则是实现开闭原则的重要途径之一,它降低了客户端与实现模块之间的耦合。
(2). 由于在软件设计中,细节具有多变性,而抽象层则相对稳定,因此以抽象为基础搭建起来的架构要比以细节为基础搭建起来的架构要稳定得多。这里的抽象指的是接口或者抽象类,而细节是指具体的实现类。
(3). 使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给它们的实现类去完成。
2. 作用
(1). 依赖倒置原则可以降低类间的耦合性。
(2). 依赖倒置原则可以提高系统的稳定性。
(3). 依赖倒置原则可以减少并行开发引起的风险。
(4). 依赖倒置原则可以提高代码的可读性和可维护性。
3. 实现方法和案例
(1). 实现的时候要注意这几点:
A. 每个类尽量提供接口或抽象类,或者两者都具备。
B. 变量的声明类型尽量是接口或者是抽象类。
C. 任何类都不应该从具体类派生。
D. 使用继承时尽量遵循里氏替换原则。
(2). 案例
业务层中的UserService1直接依赖MySQLHelp,如果要改连接SQLServer数据库,不得不改业务代码。 而UserService2类,依赖的是ISqlHelp接口,高层调用的时候,需要连接哪个数据库,直接传入即可。
数据库相关类
/// <summary> /// 数据库连接抽象接口 /// </summary> public interface ISqlHelp { public bool IsExist(string userAccount,string userPwd); public void Add(); public void Del(); public void Modify(); } /// <summary> /// MySQL帮助类 /// </summary> public class MySQLHelp : ISqlHelp { public bool IsExist(string userAccount, string userPwd) { Console.WriteLine($"MySQL数据库查询用户是否存在"); return true; } public void Add() { Console.WriteLine($"MySQL数据库Add成功"); } public void Del() { Console.WriteLine($"MySQL数据库Del成功"); } public void Modify() { Console.WriteLine($"MySQL数据库Modify成功"); } } /// <summary> /// SQLServer数据库操作类 /// </summary> public class SQLServerHelp : ISqlHelp { public bool IsExist(string userAccount, string userPwd) { Console.WriteLine($"sqlserver数据库查询用户是否存在"); return true; } public void Add() { Console.WriteLine($"sqlserver数据库Add成功"); } public void Del() { Console.WriteLine($"sqlserver数据库Del成功"); } public void Modify() { Console.WriteLine($"sqlserver数据库Modify成功"); } }
相关业务类
/// <summary> /// 用户业务逻辑类 /// 直接依赖MySQLHelp,如果要改成SQLServerHelp,类似的这种类都需要改 /// </summary> public class UserService1 { public MySQLHelp _help { get; set; } public UserService1(MySQLHelp help) { this._help = help; } /// <summary> /// 模拟校验登录接口 /// </summary> public void CheckLogin(string userAccount,string userPwd) { _help.IsExist(userAccount,userPwd); } } /// <summary> /// 用户业务逻辑 /// 依赖抽象,需要链接什么数据库在实例化的时候传入什么对象即可 /// </summary> public class UserService2 { public ISqlHelp _help { get; set; } public UserService2(ISqlHelp help) { this._help = help; } /// <summary> /// 模拟校验登录接口 /// </summary> public void CheckLogin(string userAccount, string userPwd) { _help.IsExist(userAccount, userPwd); } }
高层调用
{ Console.WriteLine("--------------------------依赖倒置--------------------------------"); //1.依赖具体的后果, 无法直接切换成SQLServerHelp UserService1 uService1 = new UserService1(new MySQLHelp()); //UserService1 uService2 = new UserService1(new SQLServerHelp()); //报错,不支持这么写 //2.依赖抽象的好处,可以直接切换 UserService2 us1 = new UserService2(new MySQLHelp()); UserService2 us2 = new UserService2(new SQLServerHelp()); }
二. 单一职责原则
1. 定义
单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。
通俗的来讲:一个类负责一个职责。(同样,方法层次上也存在单一职责原则)
违背单一职责原则带来的问题:
(1). 一个职责的变化可能会削弱或者抑制这个类实现其他职责的能力
(2). 当客户端需要该对象的某一个职责时,不得不将其他不需要的职责全都包含进来,从而造成冗余代码或代码的浪费。
2. 作用
(1). 优点:
A. 降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
B. 提高类的可读性。复杂性降低,自然其可读性会提高。
C. 提高系统的可维护性。可读性提高,那自然更容易维护了。
D. 变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。
(2). 相关概念
单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。
A. 高内聚:内聚是指类内部的属性和行为,高内聚就是指:一个类的属性和行为与这个类非常密切,称为高内聚。
B. 低耦合:耦合是指类与类之间或者模块与模块之间的联系,低耦合就是指:耦合度低,易重用、使用灵活。
3. 实现方法和案例
比如:老师和辅导员各自负责不同的业务。
/// <summary> /// 老师 /// </summary> public class Teacher { public void Fun1() { Console.WriteLine("备课"); } public void Fun2() { Console.WriteLine("教学"); } public void Fun3() { Console.WriteLine("考试"); } } /// <summary> /// 辅导员 /// </summary> public class Counsellor { public void Fun1() { Console.WriteLine("出勤统计"); } public void Fun2() { Console.WriteLine("班会组织"); } public void Fun3() { Console.WriteLine("收费"); } }
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。