面向对象编程OOP的五个原则

五原则自然是众所周知的OO五原则:单一职责原则、开放封闭原则、Liskov替换原 则、依赖倒置原则和接口隔离原则

单一职责原则:就是就一个类而言,应该仅有一个引起它的变化的原因。换句话说,一个类的功能要单一,只做与它相关的事情
单一职责原则的好处
第一、有助于我们分析和编码的思路的清晰。当你的代码里有了三层或以上的if语句或for语句的嵌套的时候,你不要跟我说,你已经把问题分析得很清楚了。多层嵌套的if或for语句只能说明你还没有把问题分析清楚。
第二、使我们的编码、测试和维护变得简单。
第三、将一个个复杂的问题简单化以后,易于代码的重用。当你的代码的多个功能搅和在一起的时候,你是没办法考虑代码的重用的,因为你的每一处代码都有不同。
第四、易于系统的扩展

开放-封闭原则(OCP:The Open-Closed Principle)
软件实体(类,模块,函数等等)应该是可以扩展的,但是不可修改的。
1. “对于扩展是开放的” (Open for extension)。这意味着模块的行为是可以扩展的,当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为,换句话说,我们可以改变模块的功能。
2. “对于更改是封闭的” (Closed for modification)。对模块行为进行扩展时,不必改动模块的源代码或者二进制代码,模块的二进制可执行版本,无论是可链接的库、DLL或JAVA 的.jar文件,都无需改动。

一般而言,无论模块是多么的“封闭”,都会存在一些无法对之封闭的变化,没有对于所有情况都贴切的模型。
遵循OCP的代价也是昂贵的。创建正确的抽象是要花费开发时间和精力的。同时,那些抽象也增加了软件的复杂性。开发人员有能力处理的抽象数量也是有限的。显然,我们希望把OCP的应用限定在可能会发生的变化上。

隔离变化:
1. “只受一次愚弄”,这意味着在我们最初编写代码时,假设变化不会发生;当变化发生时,我们就创建抽象来隔离以后发生的同类变化。
2. 刺激变化。我们首先编写测试 ,我们使用很短的迭代周期进行开发——一个周期为几天而不是几周 ,我们在加入基础结构之前就开发特性,并且经常性的把那些特性展示给涉众 ,我们首先开发最重要的特性 ,尽早的、经常的发布软件

Liskov替换原则(LSP)
对于LSP可以做如下解释:
子类型(subtype)必须能够替换掉它们的基类型(base type)
Barbara Liskov首次写下这个原则是在1988年。她说到,
这里需要如下替换性质: 若对每个类型S的对象o1,都存在一个类型T的对象o2,使得在所有针对T编写的程序P中,用o1替换o2后,程序P行为功能不变,则S是T的子类型。
OOD中IS-A关系是就行为方式而言的,行为方式是可以进行合理假设的,是客户程序所依赖的。
基于契约设计(Design By Contract DBC),类的编写者显式的规定针对类的契约。客户代码的编写者通过该契约获悉可以依赖的。契约是通过为每个方法声明的前置条件(preconditions)和后置条件(postconditions)来指定的。要使一个方法得以执行,前置条件必须为真。执行完毕后,该方法要保证后置条件为真。
OCP是OOD中很多说法的核心。如果这个原则应用得有效,应用程学就会具有更多的可维护、可重用性以及健壮性。LSP是使OCP成为可能的主要原则之一。正是子类型的可替换性才使得使用基类型的模块在无需修改的情况下就可以扩展。这种可替换性必需是开发人员可以隐式依赖的东西。因此,如果没有显式的强制基类类型的契约,那么代码就必须良好的并且明显的表达出这一点。
术语“IS-A”的含意过于宽泛以至于不能作为子类型的定义。子类型的正确定义是“可替换性”的,这里的可替换性可以通过显式或者隐式的契约来定义。


接口隔离原则(ISP--Interface Segregation Principle):
使用多个专门的接口比使用单一的总接口要好。
一个类对另外一个类的依赖性应当是建立在最小的接口上的。
一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。
“不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。”这个说得很明白了,再通俗点说,不要强迫客户使用它们不用的方法,如果强迫用户使用它们不使用的方法,那么这些客户就会面临由于这些不使用的方法的改变所带来的改变。

依赖倒置原则DIP(Dependency-Inversion Principles)

在传统的结构化编程中,最上层的模块通常都要依赖下面的子模块来实现,也称为高层依赖低层!

DIP原则就是要逆转这种依赖关系,让高层模块不要依赖低层模块.

教科书上的定义:
第1点:高层模块不依赖底层模块,两者都依赖抽象
第2点:抽象不应该依赖于细节,细节应该依赖于抽象

每个较高层次都为它所需要的服务声明一个抽象接口,较低的层次实现这些抽象接口,每个高层类都通过该抽象接口使用下一层的服务,接口属于高层,低层要实现高层的接口,因此现在是低层依赖于高层.
是依赖关系倒置和接口所有权的倒置.

启发式规则:
1.任何变量都不应该持有一个指向具体类的指针或者引用.
2.任何类都不应该从具体类派生(始于抽象,来自具体)
3.任何方法都不应该覆写它的任何基类中的已经实现了的方法.

这个原则对于那些虽然具体但是却稳定的类来说似乎并不是很合适, 如果一个类不太会改变, 而且也不太可能创建其他的派生类,那么依赖它似乎并没有太大的危害。比如java的String类。

本文来自租赁宝网技术支持,参考网站:http://www.zulinbao.com

posted @ 2010-07-29 15:16  systemxgl  阅读(704)  评论(0编辑  收藏  举报