设计模式|设计原则之依赖倒置原则

版权声明:本文为博主原创文章,未经允许不得转载。 https://blog.csdn.net/qq_24672657/article/details/82988654

设计模式|设计原则之依赖倒置原则

记录对设计模式学习的过程

前言

  • 定义:高层模块不应以依赖低层模块,二者都应依赖其抽象

  • 抽象不应该依赖细节;细节应该依赖抽象

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

  • 优点:低耦合 、、、、等等

详细概念可以网上查询

案例实验

有一个查询数据的类SearchDao.java

package com.dsdj.design.principle.dependenceinversion;

/**
 * @ClassName SearchDao
 * @Description TODO
 * @Author dsdj
 * @Date 2018/10/9 下午7:46
 * @Version 1.0
 **/
public class SearchDao {
    
    public void getUsers(){
        System.out.println("查询人员的功能");
    }
    public void getBooks(){
        System.out.println("查询图书的功能");
    }
}

测试类


package com.dsdj.design.principle.dependenceinversion;

/**
 * @ClassName Test
 * @Description TODO
 * @Author dsdj
 * @Date 2018/10/9 下午7:50
 * @Version 1.0
 **/
public class Test {
    public static void main(String[] args) {
        SearchDao searchDao = new SearchDao();
        searchDao.getBooks();
        searchDao.getUsers();
    }
}

如果我们需要新增一个查询课程的类,只要再添加一个方法就好了,这个是典型的面向实现的编程。

新增需求,我们需要查找课程的集合,该怎么写呢?

需要在SearchDao中添加getCourse()的方法,然后在Test中重新调用getCourse()方法

是不是觉得这样做很麻烦?

问题来了

  • 这个类需要经常修改,导致扩展性比较差

  • 上面的例子,Test.java是高层次的类,SearchDao.java是低层次的类。根据依赖导致的原则,高层次的类是不依赖低层次的模块的。Test依赖SearchDao的具体实现。导致没增加一个功能,只能去底层模块添加修改,高层模块才能使用。

解决问题

1.进行抽象,提取公共方法getList();

/**
 * @ClassName GetListDao
 * @Description TODO
 * @Author dsdj
 * @Date 2018/10/9 下午8:14
 * @Version 1.0
 **/
public interface GetListDao {
    void getList();
}

2.对每个实现,写一个实现类

实现获取用户的类

public class UserDao implements GetListDao {
    public void getList() {
        System.out.println("获取User的集合");
    }
}

实现获取图书的类

public class BookDao implements GetListDao {
    public void getList() {
        System.out.println("获取book的集合");
    }
}

3.重写SearchDao

package com.dsdj.design.principle.dependenceinversion;

/**
 * @ClassName SearchDao
 * @Description TODO
 * @Author dsdj
 * @Date 2018/10/9 下午7:46
 * @Version 1.0
 **/
public class SearchDao {

    private GetListDao getListDao;

    public SearchDao(GetListDao getListDao){
        this.getListDao=getListDao;
    }

    public void setGetListDao(GetListDao getListDao) {
        this.getListDao = getListDao;
    }

    public void searchlist(){
        getListDao.getList();
    }

}

Test

public class Test {
    public static void main(String[] args) {
//        SearchDao searchDao = new SearchDao();
//        searchDao.getBooks();
//        searchDao.getUsers();
        // 重构之后的写法
        SearchDao searchDao = new SearchDao(new BookDao());
        // 获取图书
        searchDao.searchlist();
        // 获取用户
        searchDao.setGetListDao(new UserDao());
        searchDao.searchlist();

    }
}

这样是不是就很有层次感了,

根据依赖倒置的原则:高层没有依赖底层的模块。例如SearchDao是高层模块,并没有依赖底层的UserDao、BookDao模块。有新需求的时候,只要再底层模块进行扩展。获取其他数据不会影响已经写好的模块。

相对于细节的多样性,抽象就稳定多了,故以抽象为基础搭建起来的架构就稳定多了。

现在我们再回头看看spring的依赖注入、控制反转,是不是有了新的理解了。代码不需要费心具体的实现类,把具体的实现类的权利交给容器负责就好了。

效果

我们回来再看之前的需求:新增一个获取课程的需求

我们可以怎么写呢?

写一个实现类CourseDao

public class CourseDao implements GetListDao {
    public void getList() {
        System.out.println("获取course集合");
    }
}

Test调用

public class Test {
    public static void main(String[] args) {
//        SearchDao searchDao = new SearchDao();
//        searchDao.getBooks();
//        searchDao.getUsers();
        // 重构之后的写法
        SearchDao searchDao = new SearchDao(new BookDao());
        // 获取图书
        searchDao.searchlist();
        // 获取用户
        searchDao.setGetListDao(new UserDao());
        searchDao.searchlist();
        
        // 新增需求:获取课程
        searchDao.setGetListDao(new CourseDao());
        searchDao.searchlist();
    }
}

在这里插入图片描述

运行结果
在这里插入图片描述

这样就可以不破坏原来的代码而实现新的功能了。

总结

  • 对依赖倒置原则和开闭原则是相互联系的,在使用到依赖倒置原则过程中我们也不知不觉用到了开闭原则
  • 对依赖倒置原则的学习,可以对一些框架的设计有新的理解

猜你喜欢

转载自blog.csdn.net/qq_24672657/article/details/82988654