zoukankan      html  css  js  c++  java
  • 依赖倒置原则

    参考:spring5核心原理与30个类手写实战

    依赖倒置原则(Dependence Inversion principle) 是指设计代码结构时,高层模块不应该依赖低层模块,二者都应该依赖其抽象.抽象不应该依赖细节,细节应该依赖抽象.通过依赖倒置,可以减少类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,并且可以降低修改程序所造成的风险.接下来看一个案例,还是以Course为例,先来创建一个Tom:

    public class Tom {
        public void studyJavaCourse(){
            System.out.println("tom正在学习java课程");
        }
        public void studyPythonCourse(){
            System.out.println("tom正在学习Python课程");
        }
    }
    

    来调用一下

        @Test
        public void testTom(){
            Tom tom = new Tom();
            tom.studyJavaCourse();
            tom.studyPythonCourse();
        }
    

    Tom热爱学习,目前正在学习Java和Python,大家都知道学习会上瘾,随着学习兴趣的暴涨,现在Tom还想学习AI的课程,这时候因为业务的扩展,要从低层到高层(调用层)修改代码.在Tom类中还想增加一个studyAiCourse()方法,在高层也要追加调用.如此一来,系统发布以后,实际上是非常不稳定的,在修改代码的同时也会带来意想不到的风险.接下来优化代码,创建一个客户才能的抽象ICourse接口:

    public interface Icourse {
        void study();
    }
    

    然后编写JavaCourse类:

    public class JavaCourse implements Icourse {
        @Override
        public void study() {
            System.out.println("正在学习Java课程");
        }
    }
    

    在实现PythonCourse类:

    public class PythonCourse implements Icourse {
        @Override
        public void study() {
            System.out.println("正在学习Python课程");
        }
    }
    
    

    修改Tom类:

    public class Tom {
        public void study(Icourse course){
            course.study();
        }
    }
    

    来看调用代码

    @Test
        public void testTom(){
            Tom tom = new Tom();
            tom.study(new JavaCourse());
            tom.study(new PythonCourse());
        }
    

    这时候再看地阿妈,Tom的兴趣无论怎么暴涨,对于新的课程,只需要新建一个类,通过传参的方式告诉Tom,而不需要修改低层代码.实际上这是一种大家非常熟悉的方式,叫依赖注入.注入的方式还有构造器方式和Setter方式.我们来看构造器注入方式:

    public class Tom {
        private Icourse icourse;
        public Tom(Icourse icourse){
            this.icourse = icourse;
        }
        public void study(){
            icourse.study();
        }
    }
    

    看调用代码:

    @Test
        public void testTom(){
            Tom tom = new Tom(new JavaCourse());
            tom.study();
        }
    

    根据构造器方式注入,在调用时,每次都要创建实例.如果Tom是全局单例,则我们就只能选择用Setter方法来注入,继续修改Tom类的代码:

    public class Tom {
        private Icourse icourse;
        public void setIcourse(Icourse icourse){
            this.icourse = icourse;
        }
        public void study(){
            icourse.study();
        }
    }
    

    看调用代码:

        @Test
        public void testTom(){
            Tom tom = new Tom();
            tom.setIcourse(new JavaCourse());
            tom.study();
            tom.setIcourse(new PythonCourse());
            tom.study();
        }
    

    大家切记,以抽象为基准比以细节为基准搭建起来的架构要稳定得多,因此在拿到需求之后,要面向接口编程,先顶层再细节地设计代码结构.

  • 相关阅读:
    Chapter 03Using SingleRow Functions to Customize Output(03)
    Chapter 03Using SingleRow Functions to Customize Output(01)
    Chapter 04Using Conversion Functions and Conditional ExpressionsNesting Functions
    Chapter 04Using Conversion Functions and Conditional ExpressionsGeneral Functions
    Chapter 11Creating Other Schema Objects Index
    传奇程序员John Carmack 访谈实录 (zz.is2120)
    保持简单纪念丹尼斯里奇(Dennis Ritchie) (zz.is2120.BG57IV3)
    王江民:传奇一生 (zz.is2120)
    2011台湾游日月潭
    2011台湾游星云大师的佛光寺
  • 原文地址:https://www.cnblogs.com/liuzhidao/p/13724283.html
Copyright © 2011-2022 走看看