依赖倒置原则学习总结

定义:
高层模块不应该依赖底层模块,二者都应该依赖其抽象
抽象不应该依赖细节;细节应该依赖抽象
针对接口编程,不要针对实现编程
优点:
可以减少类间的耦合性、提高系统稳定性、提高代码可读性和维护性,可降低修改程序锁造成的风险.
实践代码:

v1.0

假设底层有一个学生类,具有学习java课程和python课程的功能,应用层需要调用这个学生来学习,一开始是这样的 :

/**
 * 定义一个学生对象
 */
public class Student {

    public void javaStudy(){
        System.out.println("学习java课程");
    }
    public void pythonStudy(){
        System.out.println("学习python课程");
    }
}
/**
* 应用层
*/

public class DependencyInversionTest {
    public static void main(String[] args) {

/*        Student student = new Student();
        student.study(new JavaCourse());*/

        Student student = new Student();
        student.javaStudy();
        student.pythonStudy();
    }
}

应用new一个学生对象,然后调用学生对象的学习方法,如果后期需要实现新的功能就要去修改已经定义好的学生类,就涉及到了要修改底层代码,这就可能会引发一些不可预知的风险,同事也不符合开闭原则.

V2.0

针对这种情况进行相应结构调整,将学生类的具体学习方法抽象为一个接口,交由单独的类来实现:

/**
 * 定义一个抽象的接口 具有study方法
 */
public interface ICourse {
    void study();
}

/**
 * 定义一个学生对象 具有学习功能 该学习方法传入抽象接口ICourse
 */
public class Student {

    public void study(ICourse iCourse) {
        iCourse.study();
    }

}
/**
 * 具体实现接口的学习功能
 */
public class JavaCourse implements ICourse {
    @Override
    public void study() {
        System.out.println("学习java编程");
    }
}
/**
 * 具体实现接口的学习功能
 */
public class PythonCourse implements ICourse {
    @Override
    public void study() {
        System.out.println("学习python编程");
    }
}


public class DependencyInversionTest {
    public static void main(String[] args) {

        Student student = new Student();
        student.study(new JavaCourse());
        student.study(new PythonCourse());
    }
}

通过改造后 应用需要调用学生的相关功能时,只需传入接口实现类即可,当需要添加新的功能时,直接创建一个全新的类来实现接口即可,无需修改原来的代码,也降低了耦合度,可读性和维护性也有了相应的提高.

V3.0

再次调整student的结构,通过构造器注入.

public class Student {

    private ICourse iCourse;

    public Student(ICourse iCourse) {
        this.iCourse = iCourse;
    }

    public void study() {
        iCourse.study();
    }
}


public class DependencyInversionTest {
    public static void main(String[] args) {
        Student student = new Student(new JavaCourse());
        student.study();
    }
}

这样应用在调用student的study功能时 只需在创建时传入接口实现类即可.

V4.0

当student为单例模式时,可以再次改造,通过添加set方法来赋值调用

public class Student {

    private ICourse iCourse;


    public void study() {
        iCourse.study();
    }

    public void setiCourse(ICourse iCourse) {
        this.iCourse = iCourse;
    }
}

public class DependencyInversionTest {
    public static void main(String[] args) {
        Student student = new Student();
        student.setiCourse(new JavaCourse());
        student.study();
    }
}

个人总结:

在平时的开发过程其实很多程序的源码都应用到了这种原则,应用好这种原则可以让开发和后期维护变得很轻松,整体代码也更有水平.