知识卡片
分离接口:不要每个类都用
内容
分离接口的核心机制很简单:接口定义在一个包里,实现放在另一个包里,利用”实现依赖接口、接口不依赖实现”这个单向关系——依赖接口的客户包完全不需要知道实现包的存在,实现包反过来依赖接口包。典型使用场景包括:框架包里的抽象代码需要调用特定应用代码;某一层要调用另一层但又不该知道对方的存在(比如领域层调用数据映射器);需要调用另一个团队开发的功能,又不想被对方API的变动直接绑架。但作者观察到一种常见的过度使用:有些开发者给自己写的每一个类都套上分离接口。作者明确认为这样”过犹不及”,尤其在普通应用开发中不值得——保持接口和实现分离需要额外的工作量(往往还得配一套工厂类来做实例化),如果一开始就把接口和实现放在一起,将来真需要拆分时,也不过是一次简单的重构而已,完全可以推迟到真正需要时再做。作者给出的实用判断标准是:只有当你确实想打破两部分之间的依赖关系,或者同一个接口未来会有多个独立实现时,才值得引入分离接口。此外,如果打算在编译期强制检查包间依赖规则(大型系统里这很有价值,小系统则无关紧要),分离接口才会体现出实打实的收益;否则日常开发里”创建对象时依赖实现类、后续只通过接口使用它”这种松散约定通常就已经够用。可迁移启发:任何为了”解耦”而普遍套用的设计手段,都该先问一句——当下是否真的存在具体的解耦诉求(多实现、打破循环依赖、强制依赖规则),还是只是把它当成一种默认的”最佳实践”照抄;分离接口和它带来的额外工厂类维护成本,只有在真正的解耦诉求出现时才划算,否则就是提前支付了一笔不必要的复杂度。
参考来源
- 位置:《企业应用架构模式》第二部分"模式"之"第18章 基本模式"之"18.4.2 使用时机"(源文件:_epub-src/OEBPS/Text/000219.html)
- 结论依据:原文说明"我碰到过许多开发者,他们为编定的每一个类都使用了分离接口。我觉得这有些过犹不及,尤其对普通应用程序的开发而言……我建议只有当你希望打破依赖关系,或者同一接口有多个独立的实现才使用一个分离接口。如果你把接口和实现放在一起,再在将来某一时刻分开它们也不只过是一个简单的软件重构,完全可以将它推迟到你必须如此时再实施",直接支撑本卡结论。
- 原始内容:我建议只有当你希望打破依赖关系,或者同一接口有多个独立的实现才使用一个分离接口。