type
status
date
slug
summary
tags
category
icon
password
Property
Nov 2, 2022 06:13 AM
这是我们习惯上的层次依赖示例,策略层依赖方法层,方法层依赖工具层。
这样分层依赖的一个潜在问题是,策略层对方法层和工具层是传递依赖的,下面两层的任何改动都会导致策略层的改动,这种传递依赖导致的级联改动可能会导致软件维护过程非常糟糕。
解决办法是利用依赖倒置的设计原则,每个高层模块都为它所需要的服务声明一个抽象接口,而低层模块则实现这些抽象接口,高层模块通过抽象接口使用低层模块。
这样,高层模块就不需要直接依赖低层模块,而变成了低层模块依赖高层模块定义的抽象接口,从而实现了依赖倒置,解决了策略层、方法层、工具层的传递依赖问题。
我们日常的开发通常也要依赖抽象接口,而不是依赖具体实现。比如 Web 开发中,Service 层依赖 DAO 层,并不是直接依赖 DAO 的具体实现,而是依赖 DAO 提供的抽象接口。那么这种依赖是否是依赖倒置呢?其实并不是,依赖倒置原则中,除了具体实现要依赖抽象,最重要的是,抽象是属于谁的抽象。
通常的编程习惯中,低层模块拥有自己的接口,高层模块依赖低层模块提供的接口,比如方法层有自己的接口,策略层依赖方法层的接口;DAO 层定义自己的接口,Service 层依赖 DAO 层定义的接口。
但是按照依赖倒置原则,接口的所有权是被倒置的,也就是说,接口被高层模块定义,高层模块拥有接口,低层模块实现接口。不是高层模块依赖底层模块的接口,而是低层模块依赖高层模块的接口,从而实现依赖关系的倒置。
在上面的依赖层次中,每一层的接口都被高层模块定义,由低层模块实现,高层模块完全不依赖低层模块,即使是低层模块的接口。这样,低层模块的改动不会影响高层模块,高层模块的复用也不会依赖低层模块。对于 Service 和 DAO 这个例子来说,就是 Service 定义接口,DAO 实现接口,这样才符合依赖倒置原则。