七大设计原则(二):依赖倒置原则

本文通过实例讲解依赖倒置原则,强调高层模块不应依赖低层模块,而应依赖抽象。通过买书接口的案例,展示如何通过面向接口编程降低耦合度,提高代码的可维护性和扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考慕课网视频《Java设计模式精讲》:
视频作者:Geely
视频链接:https://coding.imooc.com/lesson/270.html#mid=17149

定义

高层模块不应该依赖低层模块,二者都应该依赖其抽象。

强调

抽象不应该依赖细节,细节应该依赖抽象。

针对接口编程,不要针对实现编程。

优点

可以减少类间的耦合性、提高系统稳定性,提高代码可读性和可维护性,可降低修改程序所造成的风险。

案例:清风先生通过看Java视频来提升自己。

public class JavaVideo {
    //播放的功能
    public void play(){
        System.out.println("看java的视频");
    }
}
public class MrQingFeng {
    //看视频
    public void watch(JavaVideo video){
        video.play();
    }
}

清风先生具有看的功能,并且依赖于JavaVideo这个类。接下来写测试类。

public class MainTest {
    @Test
    public void testMethod1(){
        MrQingFeng mrQingFeng = new MrQingFeng();
        JavaVideo video = new JavaVideo();
        mrQingFeng.watch(video);
    }
}

这段代码很简单,结果就是:清风先生通过看Java视频,成功的提升了自己的Java水平。但是,技术更新迭代很快,现在已经是人工智能和大数据的时代了。所以,清风先生想要开始学习Python这门语言。他还是更加倾向于视频学习。所以,清风先生想要看Python视频。但是呢,清风先生家里的播放器只支持Java格式的视频。不支持Python格式的。所以,没办法,他就放弃了。

上面的例子,就说明了,清风这个类是个高层模块,Java视频是一个低层模块。他依赖于具体的实现。如果需要看HTML、GO或者其他的视频,就要更改他所依赖的具体实现。这样耦合度很大,生产力很低,当需求变更的时候,就要面临大面积的重构。

所以,下面通过抽象,来解决这个问题。
案例:清风先生想要学习一门编程语言,大家都推荐他通过看书来学习,但是他却不知道应该买什么书。所以呢,我们就来帮帮他。
定义一个买书的接口:

package com.qfcwx.dependencyinversion;

/**
 * @ClassName: Book
 * @Author: 清风一阵吹我心
 * @Description: TODO 一个买书的接口
 * @Date: 2019/4/7 17:30
 * @Version 1.0
 **/
public interface Book {

    /**
     * 买书
     */
    void buyBook();
}

他在B公司的朋友,推荐他买Java的书来学习,因为Java的生态圈已经很完善了。所以,就要定一个类来实现上面的接口。

public class JavaBook implements Book {

    @Override
    public void buyBook() {
        System.out.println("买了一本java语言的书");
    }
}

而他在A公司的朋友说现在容器化技术,区块链这么火。所以推荐他去学习GO语言,他又计划买GO语言的书。

public class GoBook implements Book {

    @Override
    public void buyBook() {
        System.out.println("买了一本go语言的书");
    }
}

人生苦短,我用Python。谁知道,在T公司的女朋友来信了,说现在Python这么火,不选择它,还去选别的,是不是今晚想跪键盘了?
面对三方面的支援,清风先生可谓举棋不定啊。没关系,我们来帮他定。

public class MrQingFeng {

    private Book book;

    public void setBook(Book book) {
        this.book = book;
    }
    //买各种书的方法
    public void buyKindOfBook() {
        book.buyBook();
    }
}

想成为一名程序猿,成为一名优秀的程序猿,光掌握一本语言是不够的,要养成终身学习的习惯。所以,建议清风先生,把每种语言的书都买上,这样也能解决你现在的纠结情绪,还不用跪键盘了。岂不是美哉?

public class MainTest {

    public static void main(String[] args) {
        MrQingFeng mrQingFeng = new MrQingFeng();
        mrQingFeng.setBook(new JavaBook());
        mrQingFeng.buyKindOfBook();

        mrQingFeng.setBook(new PythonBook());
        mrQingFeng.buyKindOfBook();

        mrQingFeng.setBook(new GoBook());
        mrQingFeng.buyKindOfBook();
    }
}

看吧,通过依赖抽象的方式,帮清风先生解决了买书的困难。瞬间觉得自己很伟大呢。

言归正传,上面的例子,就是强调,我们要面向接口编程,不要针对其实现编程。若想扩展具体的实现,只需要实现接口,或者继承其抽象即可。
例如:清风先生又想买Netty、SpringBoot的书。当然没问题,只需要实现买书的接口就行了。不会对应用的整体架构造成影响。

知识扩展

因为清风先生依赖书这个接口,所以,需要将其注入。这里的注入方式,使用的是Setter方式。
当然还有构造器注入、接口方法注入。

构造器注入

    private Book book;
    
    public  MrQingFeng(Book book){
        this.book = book;
    }
    
    public void buyKindOfBook() {
        book.buyBook();
    }    

接口方法

    public void buyKindOfBook(Book book) {
        book.buyBook();
    }

上面说了三种接口注入的方式,在Spring中最常用的就是Setter和构造器注入,也推荐大家使用这两种方式。

即使想活成强人,也得一步步来不是,别太苦了自己,负面情绪多了就找人宣泄一下,青春加油,未来加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值