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)的更多相关文章

  1. C#软件设计——小话设计模式原则之:依赖倒置原则DIP

    前言:很久之前就想动笔总结下关于软件设计的一些原则,或者说是设计模式的一些原则,奈何被各种bootstrap组件所吸引,一直抽不开身.群里面有朋友问博主是否改行做前端了,呵呵,其实博主是想做“全战”, ...

  2. 7.12 其他面向对象设计原则3: 依赖倒置原则DIP

    其他面向对象设计原则3: 依赖倒置原则DIP  The Dependency Inversion Principle7.1 依赖倒置原则DIP The Dependency Inversion Pr ...

  3. 依赖倒置原则DIP&控制反转IOC&依赖注入DI

    依赖倒置原则DIP是软件设计里一个重要的设计思想,它规定上层不依赖下层而是共同依赖抽象接口,通常可以是上层提供接口,然后下层实现接口,上下层之间通过接口完全透明交互.这样的好处,上层不会因依赖的下层修 ...

  4. 对依赖倒置原则(DIP)及Ioc、DI、Ioc容器的一些理解

    1.概述 所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体.简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模 ...

  5. 对依赖倒置原则(DIP)及Ioc、DI、Ioc容器的一些理解(转)

    所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体.简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合 ...

  6. 依赖倒置原则(DIP)

    什么是依赖倒置呢?简单地讲就是将依赖关系倒置为依赖接口,具体概念如下: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象(父类不能依赖子类,它们都要依赖于抽象类) 2.抽象不能依赖于具体,具体 ...

  7. 设计模式学习--面向对象的5条设计原则之依赖倒置原则--DIP

    一.DIP简介(DIP--Dependency Inversion Principle): 1.高层模块不应该依赖于低层模块,二者都应该依赖于抽象.2.抽象不应该依赖于细节,细节应该依赖于抽象.   ...

  8. 深入理解JavaScript系列(22):S.O.L.I.D五大原则之依赖倒置原则DIP

    前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第5篇,依赖倒置原则LSP(The Dependency Inversion Principle ). 英文原文:htt ...

  9. IOS设计模式的六大设计原则之依赖倒置原则(DIP,Dependence Inversion Principle)

    定义 高层模块不应该依赖于低层模块,二者都应该依赖于抽象:抽象不应该依赖细节:细节应该依赖抽象. 定义解读 依赖倒置原则在程序编码中经常运用,其核心思想就是面向接口编程,高层模块不应该依赖低层模块(原 ...

  10. 依赖倒置原则DIP(面向接口编程—OOD)

    含义: 1.高层模块不应该依赖底层模块,两者都应该依赖其抽象. 2.抽象不应该依赖细节. 3.细节应该依赖抽象. 底层模块:不可分割的原子逻辑. 高层模块: 原子逻辑的再组装. 抽象:接口或者抽象类, ...

随机推荐

  1. mysql 记录根据日期字段倒序输出

    我们知道倒序输出是很简单的 select * from table order by id desc 直接这样就可以 那么现在的问题在于日期字段怎么来倒序输出 这里我们用到cast()来将指定的字段转 ...

  2. charCodeAt与fromCharCode

    charCodeAt() 方法可返回指定位置的字符的 Unicode 编码 这个返回值是 0 - 65535 之间的整数. stringObject.charCodeAt(index) /* a-z  ...

  3. SAP入行就业

    就大局势来说, 缺乏人最多的模块有abap 还有就是FICO 和MM. 如果您 英语水平特别高的话,建议您学习FICO HR 或BW. 如果您想追求高薪,那就是FICO无疑了.想快速就业或者有编程基础 ...

  4. java面向对象的核心思想

    java面向对象的特征之一:封装 1.封装性的使用 package edu.tongji.classdemo; /* 封装性 1.封装的目的:保护某些属性和方法不被外部所见 2.封装的实现 为属性和方 ...

  5. HAProxy+keepalived+MySQL 实现MHA中slave集群负载均衡的高可用

    HAProxy+keepalived+MySQL实现MHA中slave集群的负载均衡的高可用 Ip地址划分: 240    mysql_b2 242    mysql_b1 247    haprox ...

  6. Mysql 悲观锁

    转载:http://chenzhou123520.iteye.com/blog/1860954 悲观锁介绍: 悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处 ...

  7. Dictionary CPU 100%

    昨天服务器的CPU突然100%,此服务已经运行几年了,都平安无事.既然问题出现当然要找出这个遗留多年的小概率问题.出现cpu 100% 一般就是哪里出现了无法跳出的死循环. 1.获取进程的内存信息 服 ...

  8. Nginx ACCESS阶段 如何限制IP访问

    192.168.1.0/24(最大32位的子网掩码) 每个ip是8位 那么 24/8 = 3 也就是前三个二进制 是 11111111 11111111 11111111 是指子网掩码的位数.写的是多 ...

  9. JavaScript--XML DOM 总结

    XML DOM 2018-09-04 XML简介 1.什么是XML XML 指可扩展标记语言(EXtensible Markup Language) XML 是一种标记语言,很类似 HTML XML ...

  10. Web项目替换jar包中的文件的方法

    经常遇到这样的问题,需要修改jar包中的方法.应该如何做? 1.有些很人性化的框架jar包,比如SpringSecurity,可以修改配置文件指定一个新建的类,让类实现Jar包中的对应的接口就好了. ...