为什么要有设计
如何同时提高一个软件系统的可维护性和可复用性是面向对象的设计要解决的核心问题。
导致一个软件设计的可维护性较低,也就是说会随着性能要求的变化而“腐烂”的真正原因有四个:
- 过于僵硬
- 过于脆弱
- 复用率低
- 黏度过高
一个好的系统设计应该有如下的性质,这三条性质就是一个系统设计应当达到的目标。
- 可扩展性
- 灵活性
- 可插入性
软件的复用的好处有:
- 较高的生产效率
- 较高的软件质量
- 恰当使用复用可改善系统的可维护性
在面向对象的语言中,数据的抽象化、继承、封装和多态性是几项最重要的语言特性,这些特性使得一个系统可以在更高的层次上提供可复用性。数据的抽象化和继承关系使得概念和定义可以复用;多态性使得实现和应用可以复用;而抽象化和封装可以保持和促进系统的可维护性。
在一个设计得当的系统中,每一个模块都相对于其它模块独立存在,并只保持与其它模块的尽可能少的通信。这样一来,在其中某一个模块发生代码修改的时候,这个修改的压力不会传递到其它的模块。
设计原则
常见的设计原则有:
-
“开闭”原则(Open-Closed Principle)
“开闭”原则讲的是:一个软件实体应当对扩展开放,对修改关闭。其英文原文是:Software entities should be open for extension,but closed for modification.满足开闭原则的设计可以给一个软件系统两个无可比拟的优越性:1.通过扩展已有的软件系统,可以提供新的行为,以满足对软件的新需求,使变化中的软件系统有一定的适应性和灵活必。2.已有的软件模块,特别是最重要的抽象层模块不能再修改,这就使变化中的软件系统有一定的稳定性和延续性。
-
里氏代换原则(Liskov Substitution Principle)
里氏代换原则指一个软件实体如果使用的是一个基类的话,那么一定适用于其子类,而且它根本不能察觉出基类和子类对象的区别。里氏代换原则是继承复用的基石。只有当衍生类可以替换掉基类,软件单位的功能不会受到影响时,基类才能真正被复用,而衍生类也才能在基类的基础上增加新的行为。
-
依赖倒转原则(Dependency Inversion Principle)
依赖倒转原则要求客户端依赖于抽象耦合,依赖倒转原则的表述是:抽象不应当依赖于细节;细节应当依赖于抽象。(Abstractions should not depend upon details,Details should depend upon abstractions)依赖倒转原则的另一种表达是:要针对接口编程,不要针对实现编程。(Program to an interface, not an implementation)
-
接口隔离原则(Interface Segregatioon Principle)
接口隔离原则,指一个类对另外一个类的依赖性应用是建立在最小的接口上的。
-
组合/聚合复用原则(Composition/Aggregation Principle)
组合/聚合复用原则,就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用已有功能的目的。另一个更简短的表述:要尽量使用合成/聚合,尽量不要使用继承。
-
迪米特法则(Law of Demeter)
迪米特法则又叫做最少知识原则(Least Knowledge Principle),就是说,一个对象应当对其它对象有尽可能少的了解。迪米特法则有很多表达方式,较有代表性的有:只与你直接的朋友们通信(Only talk to your immediate friends)。不要跟“陌生人”说话(Don’t talk to strangers)。
本文上述均节选摘抄自阎宏博士的《Java与模式》一书