Spring Web MVC 依赖倒置原则分析

用户头像
王鹏飞
关注
发布于: 2020 年 06 月 16 日
Spring Web MVC 依赖倒置原则分析

依赖原则的基本概念(DIP)



DIP - Dependency Inversion Principle

  • 高层模板块不能依赖低层模块,而大家都依赖于抽象

  • 抽象不能依赖实现,而是实现依赖抽象

DIP - 倒置了什么?

  • 模块或包的依赖关系

  • 开发顺序和职责

软件的层次化

  • 高层决定层

  • 高层被重用

Spring MVC Context Hierarchy

Spring MVC 是封装了前端 controller 控制层的servlet框架。如图所展示Spring的 DispatchServlet 容器由含两个主要的模块组成 Servlet WebApplicationContext 和 Root WebApplicationContext。Servlet WebApplicationContext 作为 Root WebApplicationContext 的子集有着更加细分的职责。

那么依赖倒置的原则可以具体体现在如下几个方面:

  • 以Servlet WebApplicationContext 中的Bean类型 HandlerMapping 为例,HandlerMapping 是一个高层抽象的接口声明,主要职责为request请求添加前置或后置拦截器功能。其最主要的两个底层实现 RequestMappingHandlerMapping 是对 @RequestMapping 方法注解声明的实现,SimpleUrlHandlerMapping 是对 URI 模式匹配的实现。 高层模块的实现无需依赖于低层模块,而低层实现依赖于高层 HandlerMapping 的抽象声明。

  • 从模块和包的依赖关系和开发顺序和职责角度观察发现 WebApplicationContext 抽象接口声明属于包org.springframework.web.context 继承自 org.springframework.context 下的 ApplicationContext。低层的 WebApplicationContext 扩展了高层 ApplicationContext 的抽象声明。ApplicationContext 的职责属于更高一层的整个容器的抽象声明,WebApplicationContext 的职责则聚焦于 web 问题域内的抽象声明。在开发顺序来看如上面提到的 HandlerMapping 是针对不同低层问题的实现,在编码完成之后可以在不修改 WebApplicationContext 的前提下嵌入模块中使用。

  • 从软件的层次化角度来看 WebApplicationContext 已经明确了整个模块的领域问题的抽象方向。Servlet WebApplicationContext(Servlet的实现) 继承 WebApplicationContext 的抽象声明并将实现的边界放在控制层,视图层。可以说是 WebApplicationContext 决定了 Servlet WebApplicationContext 的领域问题的大方向。如过需要扩展 web 领域其他问题可以重用 WebApplicationContext 产生一个新的 XXXX WebApplicationContext。

接口隔离原则设计缓存 Cache 工具类

将缓存工具类 Cache 进行改造按照接口隔离原则进行改造

public class Cache {
public void put(Object key, Object value) {
}
public void delete(Object key) {
}
public Object get(Object key) {
return null;
}
public void reBuild(Object conf) {
}
}

提示:cache 实现类中有四个方法,其中 put get delete 方法是需要暴露给应用程序的,rebuild 方法是需要暴露给系统进行远程调用的。如果将 rebuild 暴露给应用程序,应用程序可能会错误调用 rebuild 方法,导致 cache 服务失效。按照接口隔离原则:不应该强迫客户程序依赖它们不需要的方法。也就是说,应该使 cache 类实现两个接口,一个接口包含 get put delete 暴露给应用程序,一个接口包含 rebuild 暴露给系统远程调用。从而实现接口隔离,使应用程序看不到 rebuild 方法。

类图设计如下:

Java 代码样例:

public interface BaseCacheOperationInterface {
void put(Object key,Object value);
void delete(Object key);
Object get(Object key);
}



public interface ReBuildCacheOperationInterface {
void reBuild(Object conf);
}



public interface CacheOperationInterface extends BaseCacheOperationInterface,ReBuildCacheOperationInterface {
}



public class CacheOperationInterfaceImpl implements CacheOperationInterface {
/**
* put get delete 方法是需要暴露给应用程序
* @return
*/
public static BaseCacheOperationInterface getCacheOperationInterfaceForRemote(){
return new CacheOperationInterfaceImpl();
}
/**
* rebuild 暴露给系统远程调用
* @return
*/
public static ReBuildCacheOperationInterface getReBuildCacheOperationInterfaceForRemote(){
return new CacheOperationInterfaceImpl();
}
/**
* 全部暴露给系统远程调用
* @return
*/
public static CacheOperationInterface getCacheOperationInterfaceForRemote(){
return new CacheOperationInterfaceImpl();
}
@Override
public void put(Object key, Object value) {
}
@Override
public void delete(Object key) {
}
@Override
public Object get(Object key) {
return null;
}
@Override
public void reBuild(Object conf) {
}
}



public class CacheOperationDemo {
/**
* 调用用例
* @param args
*/
public static void main(String[] args) {
//put get delete 方法是需要暴露给应用程序
BaseCacheOperationInterface baseCacheOperationInterface = CacheOperationInterfaceImpl.getCacheOperationInterfaceForRemote();
baseCacheOperationInterface.delete("key");
baseCacheOperationInterface.get("key");
baseCacheOperationInterface.put("key","value");
//rebuild 暴露给系统远程调用
ReBuildCacheOperationInterface reBuildCacheOperationInterface = CacheOperationInterfaceImpl.getReBuildCacheOperationInterfaceForRemote();
reBuildCacheOperationInterface.reBuild("");
}
}

似乎感受到了设计原则在代码实现上的美

总结

1.依赖倒置原则是框架设计的最核心原则之一。主要作用降低了模块之间的耦合度,提高了高层的复用性和稳定性。高层面向抽象制定规则,低层面向抽象规则负责实现。底层的变动不会影响高层 !

2.接口隔离原则是让调用者只能访问它自己的方法,不能访问到不应该访问的方法。



发布于: 2020 年 06 月 16 日 阅读数: 53
用户头像

王鹏飞

关注

还未添加个人签名 2019.06.11 加入

还未添加个人简介

评论

发布
暂无评论
Spring Web MVC 依赖倒置原则分析