4.3 依赖倒置原则

一. 依赖倒置原则的定义

1.核心思想

依赖倒置原则(Dependence Inversion Principle,DIP)

*1.高层模块 不应该依赖 低层模块, 二者都应该依赖其抽象;

*2.抽象 不应该依赖 细节, 细节 应该依赖 抽象; 接口和抽象类价值在于设计;

*3.依赖倒转(倒置)的中心思想是面向接口编程,要去(面向)实现接口,而不是继承或调用实现类;

*4.依赖倒转原则的设计理念:

模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;

相对于细节的多变性,抽象的东西要稳定的多,以抽象为基础搭建的框架比以细节为基础

的架构要稳定的多,在java中,抽象指接口或抽象类(抽象战略方法),细节就是具体的实现类(多变战术实现);

使用接口或抽象类的目的是制定好规范(设计),而不涉及任何具体操作,把处理细节的任务交给子实现类去完成;

2.注意事项和细节

1)注意事项

*1.低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好;

*2.变量的声明类型尽量是抽象类或接口,这样变量的引用和实际对象间,就存在一个缓冲层,利于程序的扩展和优化;

*3.继承时遵循里氏替换原则;

2)注意细节

*1.高层模块不应该依赖低层模块,两者都应该依赖于抽象;

*2.抽象不应该依赖于细节(具体实现类);

*3.细节(具体实现类)应该依赖于抽象(实现抽象);

二.依赖倒置原则的作用

1. 依赖倒置原则可以降低类间的耦合性。

2. 依赖倒置原则可以提高系统的稳定性。

3. 依赖倒置原则可以减少并行开发引起的风险。

4. 依赖倒置原则可以提高代码的可读性和可维护性。

三.依赖倒置实现方式

依赖倒置原则的目的是通过要面向接口的编程来降低类间的耦合性,所以我们在实际编程中只要遵循以下4点,就能在项目中满足这个规则。

1. 每个类尽量提供接口或抽象类,或者两者都具备;

2. 变量的声明类型尽量是接口或是抽象类;

3. 任何类都不应该从具体类派生;

4. 使用继承时尽量遵循里氏替换原则;

四.依赖关系传递的三种方式

*1.通过构造函数传递依赖对象:通过构造方法传递接口实现类 (例如构造函数的形参是抽象类或接口 Entry(Interface iView);)

*2.通过setter方法传递依赖对象:通过setter方法传递接口实现类(setListener(Interface iView){this.iView=iView;} )

*3.接口声明实现依赖对象:直接通过方法传递接口实现类

示例 IOpenAndClose 依赖 ITV

//TV接口
interface ITV{ fun play()}

//实现类
class ChangHong : ITV {
    override fun play() {
        println("长虹电视机打开了")
    }
}
/**
 * 依赖关系传递的三种方式
 * 1.基于接口传递 : 接口回调传值
 * 2.基于构造方法传递
 * 3.setter方式传递
 */
//方式1:通过接口传递实现依赖
fun func1(){
    val changHong:ChangHong= ChangHong()
    val openAndClose:OpenAndClose= OpenAndClose()
    openAndClose.open(changHong)
}
interface IOpenAndClose{
    fun open(tv:ITV)//抽象方法,接收接口
}
//实现类,通过传递接口实现类调用接口方法
class OpenAndClose : IOpenAndClose{
    override fun open(tv: ITV) { tv.play() }
}

//方式2 通过构造方法依赖传递
fun func1(){
    val changHong:ChangHong= ChangHong()
    val openAndClose: OpenAndClose = OpenAndClose(changHong)
    openAndClose.open()
}
interface IOpenAndClose{
    fun open()//抽象方法
}
//通过实现类的构造器传递接口 依赖
class OpenAndClose(tv:ITV) : IOpenAndClose{
    private val mTv: ITV = tv
    override fun open() {
        mTv.play()
    }
}

//方式3:通过Setter方法 依赖
fun func3(){
    val changHong: ChangHong = ChangHong()
    val openAndClose: OpenAndClose = OpenAndClose()
    openAndClose.setTv(changHong)
    openAndClose.open()
}
interface IOpenAndClose {
    fun open()//抽象方法
    fun setTv(tv: ITV)
}

//通过实现类调用setter方法传递依赖
class OpenAndClose : IOpenAndClose {
    private var mTv: ITV? = null
    override fun open() {
        mTv?.play()
    }
    override fun setTv(tv: ITV) {
        mTv = tv
    }
}

五.实例

让细节的具体实现类去依赖(使用)抽象类或接口,而不是让接口或抽象类去依赖细节的具体实现;依赖倒置原则在“接收消息功能程序”中的应用:

1.类图

2.代码示例

object DependenceInversion {
    @JvmStatic
    fun main(args: Array<String>) {
        val person = Person()
        person.receive(Email())
        person.receive(WeChat())
    }
}
/**
 * 需求: 完成Person接收消息的功能
 * 方式1分析
 * 1.简单,比较容易想到:通过建立具体的消息类如: Email WeChat Sms来调去他们各自的getInfo方法
 * 2.问题:这种实现会因需求而增加新类,同时,person也要新增相应的接收方法
 * 3.解决思路:引入一个抽象的接口IReceiver,表示接收者,这样Person类与接口IReceiver建立依赖
 * 4.因为Email,WeChat 等都属于IReceiver的接收范围,他们各自实现了IReceiver接口,这样我们就符合依赖倒置原则了
 * @author xuezhihui
 * @date 2020/11/23 20:03
 */
open class Person {
    //这里Person是对接口的依赖, 传参是接口的实现类
    fun receive(receiver: IReceiver?) {
        println(receiver?.getInfo())
    }
}
//信息接收器
interface IReceiver {
    fun getInfo(): String?
}

//接收E-mail信息
class Email :IReceiver {
    override fun getInfo(): String? {
        return "Email接收的信息"
    }
}
//接收微信信息
class WeChat :IReceiver {
    override fun getInfo(): String? {
        return "WeChat接收的信息"
    }
}

程序的运行结果如下:

Email接收的信息
WeChat接收的信息

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1) 优秀的程序应该是这样的:阅读时,感觉很优雅;新增功能时,感觉很轻松;运行时,感觉很快速,这就需要设计模式支撑。2) 设计模式包含了大量的编程思想,讲授和真正掌握并不容易,网上的设计模式课程不少,大多讲解的比较晦涩,没有真实的应用场景和框架源码支撑,学习后,只知其形,不知其神。就会造成这样结果: 知道各种设计模式,但是不知道怎么使用到真实项目。本课程针对上述问题,有针对性的进行了升级 (1) 授课方式采用 图解+框架源码分析的方式,让课程生动有趣好理解 (2) 系统全面的讲解了设计模式,包括 设计模式七大原则、UML类图-类的六大关系、23种设计模式及其分类,比如 单例模式的8种实现方式、工厂模式的3种实现方式、适配器模式的3种实现、代理模式的3种方式、深拷贝等3) 如果你想写出规范、漂亮的程序,就花时间来学习下设计模式吧课程内容和目标本课程是使用Java来讲解设计模式,考虑到设计模式比较抽象,授课采用 图解+框架源码分析的方式1) 内容包括: 设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML类图(类的依赖、泛化和实现、类的关联、聚合和组合) 23种设计模式包括:创建型模式:单例模式(8种实现)、抽象工厂模式、原型模式、建造者模式、工厂模式。结构型模式:适配器模式(3种实现)、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式(3种实现)。行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)2) 学习目标:通过学习,学员能掌握主流设计模式,规范编程风格,提高优化程序结构和效率的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值