如何处理好依赖关系[Reprint]

简介:

Source: http://book.csdn.net/bookfiles/383/10038314337.shtml
“依赖”是和“变化”紧密联系在一起的概念。由于依赖关系的存在,变化在某处发生时,影响会波及开去,造成很多修改工作,这就是依赖的危害。可以说,变化是始作俑者,依赖是助纣为虐。

我们可以不去拥抱变化吗?不可以。未来将越来越不可预测,这是新经济最具挑战性的方面之一。商务和技术上的瞬息万变会产生变化,这既可以看作要防范的威胁,也可以看作应该欢迎的机遇。

既然变化不可避免,我们所能做的就是处理好依赖关系,将变化造成的影响的波及范围尽量减小。

下面总结一下“面向对象设计5大原则”和良性依赖原则在应付变化方面的作用。

单一职责原则(Single-Responsibility Principle)。“对一个类而言,应该仅有一个引起它变化的原因”。本原则是我们非常熟悉地“高内聚性原则”的引申,但是通过将“职责”极具创意地定义为“变化的原因”,使得本原则极具可操作性,尽显大师风范。同时,本原则还揭示了内聚性和耦合性是“一物两面”的关系,为了降低耦合性,基本途径就是提高内聚性;如果一个类承担的职责过多,那么这些职责就会相互依赖,一个职责的变化可能会影响另一个职责的履行。其实OOD的实质,就是合理地进行类的职责分配。

开放封闭原则(Open-Closed Principle)。“软件实体应该是可以扩展的,但是不可修改”。本原则紧紧围绕变化展开,变化来临时,如果不必改动软件实体的源代码,就能扩充它的行为,那么这个软件实体的设计就是满足开放封闭原则的。如果我们预测到某种变化,或者某种变化发生了,我们应当创建抽象来隔离以后发生的同类变化。在Java中,这种抽象指抽象基类或接口;在C++中,这种抽象是指抽象基类或纯抽象基类。当然,没有对所有情况都贴切的模型,我们必须对软件实体应该面对的变化做出选择。

Liskov替换原则(Liskov-Substitution Principle)。“子类型必须能够替换掉它们的基类型”。本原则和开放封闭原则关系密切,正是子类型的可替换性,才使得使用基类型的模块无需修改就可扩充。Liskov替换原则从基于契约的设计演化而来,契约通过为每个方法声明“先验条件”和“后验条件”;定义子类时,必须遵守这些“先验条件”和“后验条件”。当前,基于契约的设计发展势头正劲,对实现“软件工厂”的“组装生产”梦想是一个有力的支持。

依赖倒置原则(Dependency-Inversion Principle)。“抽象不应依赖于细节,细节应该依赖于抽象”。本原则几乎就是软件设计的正本清源之道。因为人解决问题的思考过程是先抽象后具体,从笼统到细节的,所以我们先生产出的势必是抽象程度比较高的实体,而后才是更加细节化的实体。于是,“细节依赖于抽象”就意味着后来的依赖于先前的,这是自然而然的重用之道。而且,抽象的实体代表着笼而统之的认识,人们总是比较容易正确认识它们,而且它们本身也是不易变的,依赖于它们是安全的。依赖倒置原则适应了人类认识过程的规律,是面向对象设计的标志所在。

接口隔离原则(Interface-Segregation Principle)。“多个专用接口优于一个单一的通用接口”。本原则是单一职责原则用于接口设计的自然结果。一个接口应该保证,实现该接口的实例对象可以只呈现为单一的角色;这样,当某个客户程序的要求发生变化,而迫使接口发生改变时,影响到其他客户程序的可能性最小。

良性依赖原则。“不会在实际中造成危害的依赖关系,都是良性依赖”。通过分析不难发现,本原则的核心思想是“务实”,很好地揭示了极限编程(Extreme Programming)中“简单设计”和“重构”的理论基础。本原则可以帮助我们抵御“面向对象设计5大原则”以及设计模式的诱惑,以免陷入过度设计(Over-engineering)的尴尬境地,带来不必要的复杂性。

本文转自BlogJava 新浪blog的博客,原文链接:如何处理好依赖关系[Reprint],如需转载请自行联系原博主。

相关文章
|
6月前
|
Python
告别混乱!Python上下文管理器的自定义实践,让你的代码更加整洁有序
【7月更文挑战第6天】Python的上下文管理器通过`__enter__`和`__exit__`方法自动处理资源的获取与释放,如文件操作。使用with语句结合自定义类(如`FileManager`示例),能确保文件在使用后正确关闭,防止资源泄漏,提升代码整洁度和健壮性。自定义上下文管理器是代码模块化和错误处理的好实践。
40 0
ESM规范如何处理循环依赖的情况
ESM规范如何处理循环依赖的情况
|
8月前
|
程序员
项目中的全局异常是如何处理的
项目中的全局异常处理通常包括对预期异常(程序员手动抛出)和运行时异常的管理。项目已提供`BaseException`作为基础异常类,用于手动抛出异常,并通过`GlobalExceptionHandler`进行全局处理。`
69 4
|
8月前
在Vuex中,如何处理不同模块之间的状态同步?
在Vuex中,如何处理不同模块之间的状态同步?
69 1
|
8月前
|
前端开发 程序员
项目中异常是如何处理的
项目中设定了全局异常处理器,统一处理预期和运行时异常。预期异常由程序员手动抛出,用于异常情况的接口返回;运行时异常为不可控错误,提供统一返回格式便于前端提示和后端排查。全局异常处理器借助@RestControllerAdvice和@ExceptionHandler注解,前者标识处理器,后者按异常类型定制前端响应,如预期异常直接返回,运行时异常则调整响应内容。
114 0
|
Java Spring
解决循环依赖问题:优雅处理依赖关系的技巧
在软件开发中,依赖是不可避免的。我们经常需要在应用程序的不同组件之间建立依赖关系,以实现功能的模块化和复用。然而,有时候依赖关系可能变得复杂,甚至导致循环依赖的问题。在本文中,我们将通过项目中实际遇到的异常探讨一些解决循环依赖问题的技巧,帮助你在开发过程中优雅地处理依赖关系。
329 0
解决循环依赖问题:优雅处理依赖关系的技巧
|
安全 搜索推荐
如何避免写重复代码?两种常见的方法:抽象和组合
如何避免写重复代码?两种常见的方法:抽象和组合
272 0
大依赖部署——几个重要的概念
大依赖部署——几个重要的概念自制脑图
89 0
大依赖部署——几个重要的概念
|
存储 缓存 安全
【Spring源码】循环依赖如何处理?
面试官:“看过Spring源码吧,简单说说Spring如何解决循环依赖问题?” 大神仙:“Spring利用到了三级缓存来解决循环依赖问题”。 面试官:“三级缓存是怎么处理的?为什么一定得是三级缓存?三级缓存别是对应存储的是什么?” 大神仙:“......”
189 0
【Spring源码】循环依赖如何处理?
|
存储 分布式计算 大数据
R 包的使用、结果的重用、如何处理大数据集|学习笔记
快速学习 R 包的使用、结果的重用、如何处理大数据集。
307 0
R 包的使用、结果的重用、如何处理大数据集|学习笔记