03-依赖倒置原则(DIP)
1. 背景
类A是高层代码,类A直接依赖B,如果要将类A改为还要依赖C,则必须修改类A的代码来实现。在实际场景中,类A是高层,负责业务逻辑,类B和类C是低层模块,负责基本的原子操作,假如修改A,会给程序带来不必要的风险。
2. 定义
高层模块不直接依赖低层模块,二者都应该依赖其抽象(抽象类或接口),抽象不应该依赖细节,细节应该依赖抽象。
3. 解决方案
类A修改为依赖接口I,而类B和类C各自实现接口I,类A通过接口I间接的同类B和类C发生联系,这样就大大降低了类的A的修改几率。
4. 依赖倒置原则的核心
面向接口编程。
5. 依赖倒置原则基于一个事实
相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。在.Net中,抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
6. 从框架搭建的角度来体会依赖倒置原则的好处
三层:数据库访问层、业务逻辑层、UI调用层。
1. 数据库访问层中有一个 MySqlHelp类,提供链接MySQL数据增删改查的方法。
2. 业务逻辑层有一个登录业务 CheckLogin(MySqlHelp mysql,string userName,string pwd)。
3. UI调用层要调用CheckLogin方法,这时候实例化一个MySqlHelp对象,传到CheckLogin方法中即可。
有一个天,要求支持oracle数据,所以 数据库访问层中增加了一个oracleHelper类,UI调用层按照常规实例化了一个oracleHelper对象,传到CheckLogin方法中,发现我的天!!!!CheckLogin竟然不支持oracleHelper对象,同时发现类似的 所有业务层的方法都不支持oracleHelper类,这个时候悲剧就发生了,如果全部改业务层的方法,基本上完蛋。
所以解决方案:依赖倒置原则,即面向接口编程。
1. 数据库访问层声明一个接口IHelper,里面有增删改查方法,MySqlHelp和oracleHelper都实现IHelper接口
2. 业务逻辑层有一个登录业务改为依赖接口IHelper, CheckLogin(IHelper iHelper,string userName,string pwd)
3. UI调用层要调用CheckLogin方法,想连哪个数据,就实例化哪个 eg IHelper iHelper=new MySqlHelp(); 或者 IHelper iHelper=new oracleHelper()
然后调用CheckLogin即可
这种解决方案还有一个好处:先把接口约束定义出来了,写MySqlHelp和oracleHelper的人和 业务逻辑层的人可以同时开发了,不必等数据库访问层写完后,再写业务逻辑了。
7. 以日常生活为线索的案例
一个母亲给儿子讲书上的故事,所以有一个mother类,一个book类。
public class mother
{
public void readStorey(book bk)
{
Console.WriteLine("妈妈开始讲故事");
Console.WriteLine(bk.GetContents());
} }
public class book
{
public string GetContents()
{
return "我是书上的故事";
}
}
public static void show()
{
//下面以一个更贴切的例子说明一下这个问题
//一位母亲给儿子讲书上的故事,有一个mother类 ,一个book类
mother mt = new mother();
book bk = new book();
mt.readStorey(bk); }

突然有一天,儿子要求妈妈给他将报纸上的故事,我的天,妈妈竟然不会讲。
解决方案:mother类中readStorey类不在直接依赖book类,而是依赖book和newpaper类共同实现的接口类。
public interface IGetContents
{
string GetContents();
}
public class NewBook:IGetContents
{
public string GetContents()
{
return "我是书上的内容";
}
}
public class NewsPaper:IGetContents
{
public string GetContents()
{
return "我是报纸上的内容";
}
}
public class mother
{
public void readStorey2(IGetContents bk)
{
Console.WriteLine("妈妈升级了,会依赖倒置原则了,开始讲故事");
Console.WriteLine(bk.GetContents());
}
}
public static void show()
{
//有一天,儿子要求妈妈给他讲报纸上的故事
//有一个NewsPaper类,发现妈妈竟然不会讲报纸上的故事
//所以下面重构一下代码: 新的NewBook类,NewsPaper,新的讲故事的方法readStorey2,新的接口IGetContents
IGetContents ig1 = new NewBook();
IGetContents ig2 = new NewsPaper();
mt.readStorey2(ig1);
mt.readStorey2(ig2); }

8. 个人感悟
低层模块尽量都要有抽象类或接口,或者两者都有。
变量的声明类型尽量是抽象类或接口。
使用继承时遵循里氏替换原则。
03-依赖倒置原则(DIP)的更多相关文章
- C#软件设计——小话设计模式原则之:依赖倒置原则DIP
前言:很久之前就想动笔总结下关于软件设计的一些原则,或者说是设计模式的一些原则,奈何被各种bootstrap组件所吸引,一直抽不开身.群里面有朋友问博主是否改行做前端了,呵呵,其实博主是想做“全战”, ...
- 7.12 其他面向对象设计原则3: 依赖倒置原则DIP
其他面向对象设计原则3: 依赖倒置原则DIP The Dependency Inversion Principle7.1 依赖倒置原则DIP The Dependency Inversion Pr ...
- 依赖倒置原则DIP&控制反转IOC&依赖注入DI
依赖倒置原则DIP是软件设计里一个重要的设计思想,它规定上层不依赖下层而是共同依赖抽象接口,通常可以是上层提供接口,然后下层实现接口,上下层之间通过接口完全透明交互.这样的好处,上层不会因依赖的下层修 ...
- 对依赖倒置原则(DIP)及Ioc、DI、Ioc容器的一些理解
1.概述 所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体.简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模 ...
- 对依赖倒置原则(DIP)及Ioc、DI、Ioc容器的一些理解(转)
所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体.简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合 ...
- 依赖倒置原则(DIP)
什么是依赖倒置呢?简单地讲就是将依赖关系倒置为依赖接口,具体概念如下: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象(父类不能依赖子类,它们都要依赖于抽象类) 2.抽象不能依赖于具体,具体 ...
- 设计模式学习--面向对象的5条设计原则之依赖倒置原则--DIP
一.DIP简介(DIP--Dependency Inversion Principle): 1.高层模块不应该依赖于低层模块,二者都应该依赖于抽象.2.抽象不应该依赖于细节,细节应该依赖于抽象. ...
- 深入理解JavaScript系列(22):S.O.L.I.D五大原则之依赖倒置原则DIP
前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第5篇,依赖倒置原则LSP(The Dependency Inversion Principle ). 英文原文:htt ...
- IOS设计模式的六大设计原则之依赖倒置原则(DIP,Dependence Inversion Principle)
定义 高层模块不应该依赖于低层模块,二者都应该依赖于抽象:抽象不应该依赖细节:细节应该依赖抽象. 定义解读 依赖倒置原则在程序编码中经常运用,其核心思想就是面向接口编程,高层模块不应该依赖低层模块(原 ...
- 依赖倒置原则DIP(面向接口编程—OOD)
含义: 1.高层模块不应该依赖底层模块,两者都应该依赖其抽象. 2.抽象不应该依赖细节. 3.细节应该依赖抽象. 底层模块:不可分割的原子逻辑. 高层模块: 原子逻辑的再组装. 抽象:接口或者抽象类, ...
随机推荐
- Java 线程内 递归 Bug 一例
一个线程的run方法里使用递归方法,出了Bug. private boolean ispass(String creationId){ List<Map> maps =creationSe ...
- Java singleton 一例
org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of ...
- ASP.NET Web Service 标准SOAP开发案例代码(自定义验证安全头SOAPHeader)
using System.Xml;using System.Xml.Serialization;using System.Web.Services.Protocols;using System.Con ...
- Linux CentOS7 安装php简要过程以及nginx
Copy From https://www.cnblogs.com/freeweb/p/5425554.html 修改了下: 1. 下载php源码: wget http://cn2.php.net ...
- linux_压缩解压命令(zip/tar)
一.zip 1.压缩 格式 $ zip (选项) (文件/目录) 选项 -r 参数表示递归打包包含子目录的全部内容. -q 参数表示为安静模式,即不向屏幕输出信息. -o 表示输出文件,需在其后紧跟打 ...
- js控制浏览器全屏
HTML 5中的full screen,目前可以在除IE和opera外的浏览器中使用 ,有的时候用来做全屏API,游戏呀,等都很有用.先看常见的API element.requestFullScree ...
- python 深入浅出装饰器(decorator)--举的例子关于星级争霸2(starcraft2)
其实早就想写一篇深入浅出装饰器的文章,苦于一直没有找到很好的例子描述,自己除了在写api参数检测和日志打印的时候用到以外,其他地方也没有什么重度使用所以一直没有写. 我不会讲解装饰器的理论,还有各种基 ...
- Android x86 下运行纯ARM版APP
Android x86 默认不带houdini,运行纯ARM版会提示: 很抱歉,”xxxx”已停止运行 设置->应用兼容性->打开 终端模拟器 $ su# enable_nativebri ...
- python中 Lambda,Map,Filter,Itertools,Generator高级函数的用法
Lambda 函数 Lambda 函数是一种比较小的匿名函数--匿名是指它实际上没有函数名. Python 函数通常使用 def a_function_name() 样式来定义,但对于 lambda ...
- BZOJ2819Nim——树链剖分+线段树+Nim游戏
题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...