设计模式的原则 抽要理解

【参阅】http://www.cnblogs.com/jiangzhengjun/p/4260969.html

单一职责原则( SRP )——内聚性

定义

单一职责原则的定义: 就一个类页言,应该仅有一个引起它变化的原因 ( There should never be more than one reason for a class to change )。

单一职责原则要求一个接口或类只有一个原因引起变化,也就是 一个接口或类只有一个职责,它就是负责一件事情 。

内聚性:一个模块的组成元素之间的功能相关性。

  类的单一职责:将类的属性和行为分离。这里说的属性是指和属性相关的set/get.这样就将其分解为业务对象(BO)和业务逻辑(BL)。

  方法的单一职责:一个类可能具有好几个功能,但是不一定就必须将所有的功能放在同一个类中,可以放在不同的接口中,实现接口分离,需要时再次将其组合。【参转】。所以在使用的时候,将所有的功能分类,看应用程序的变化对那些功能会有影响,那些没有。

开 - 闭”原则( OCP )——   抽象应对一切的变化

Open-Closed Principle : Software entities should be open for extension, but closed for modification. (一个软件实体应当 对扩展开放,对修改关闭 。)

遵循开闭原则设计出的模块具有两个主要的特征。它们是:

1 、“对扩展是开放的”。这意味着模块的行为是可以扩展的,当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。换句话说,我们可以改变模块的能。

2 、“对于更改是封闭的”。对模块行为进行扩展时,不必改动模式的源代码或者二进制代码。模块的二进制可执行版本,无论是可链接的库、 DLL 或者 Java 的 ..jar 文件,都无需改动。

开闭原则提高了系统的可维护性(可扩展性 - 增、灵活性 / 可修改性 - 修、可插入性 - 替、可测试性)、可复用性。

里氏代换原则( LSP )

从“开 - 闭”原则中可以看出面向对象设计的关键是抽象,从抽象化到具体化需要使用继承关系,而是否满足继承关系则需要使用里氏代换原则( Liskov Substation principle )来验证。

定义

所有基类(泛指接口与抽象类、还有具体类也可)出现的地方,子类都可以出现。

严格表达是:如果对每一个类型的 T1 的对象 o1 ,都有类型为 T2 的对象 o2 ,使得以 T1 定义的所有程序 P 在所有的对象 o1 都代换成 02 时,程序 P 的行为没有变化,那么类型 T2 是类型 T1 的子类型。换言这,一个软件实体如果使用的是一个基类的话,那么一定适用于子类,而且它根本不能察觉出基类对象和子类对象的区别。

就像长方形不能作为正方形的父类:

否则

public   class   SmartTest {// 测试

public   void   resize (Rectangle   r ) {

while   ( r .getHeight() <=   r .getWidth()) {// 正方形会出问题

r .setWidth( r .getWidth() + 1);

}

}

会出错的。

依赖倒转原则( DIP )

定义

Dependency inversion principle :

1 、 高层模块不应该依赖底层模块,两者都应该依赖于抽象层 。

2 、抽象(接口或抽象类)不应该依赖于细节(实现)。

3 、(实现)细节应该依赖于抽象(接口或抽象类)。

【最精简的定义就是: 针对接口编程,不要针对实现编程 。】

使用接口和抽象类进行变量的类型声明、参数的类型声明、方法的返回类型声明,以及数据类型转换等;

不要针对实现编程的意思是说,不应当使用具体类进行变量 的类型声明、参数的类型声明、方法的返回类型声明,以及数据类型转换等。

要保证这一点,一个具体类应当只实现接口和抽象类中声明过的方法,而不应当给出多 余的方法。

什么是“倒转”

什么是“倒转”,要想理解它,我们看看正置吧。依赖正置就是类间的依赖是实实在在的实现类间的依赖,也就是 面向实现编程,这也是正常人的思维方式 ,我要开奔驰就依赖奔驰,要使用苹果笔记本就使用苹果笔记本。而编写程序需要的是对现实世界的事物进行抽象,抽象的结果就是有了抽象类和接口,比如宝马与奔驰抽象成小汽车,苹果笔记本与 IBM 笔记本抽象成笔记本,然后我们的程序就依赖于这些抽象,这代替了人们传统思维中的具体事物间的依赖,“倒转”就是从这里产生的。

也就是说无论是高层模块还是底层模块都没有直接的依赖关系,而是二者同依赖于接口或抽象类。

比如说,某个司机开车不是依赖于某一牌子具体的汽车,而是依赖汽车这一类(抽象出来的)

组合 / 聚合复用原则( CARP )

组合 / 聚合复用原则( Composition/Aggregation Reuse Principle )经常又叫合成复用原则( Composition Reuse Principle   或   CRP )。综是在一个新的对象里使用已有的对象,使之成为新对象的一部分,新的对象通过向这些对象的委派达到复用已有功能的目的。

该原则另一个简短的表述:尽量使用组合 / 聚合,不要使用继承。

组合 / 聚合区别

聚合表示一种弱的“拥有”关系,体现的是 A 对象可以包含 B 对象,但 B 对象不是 A 对象的一部分;

合成则是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样,一般一个合成的多重性不能超过 1 ,换言这,一个合成关系中的成分对象是不能与另一个合成关系共享的。一个成分对象在同一个时间内只能属于一个合成关系。

组合 / 聚合复用与继承复用的区别

有两种复用的方式:组合 / 聚合复用或继承复用。

组合 / 聚合复用方式可以在运行期内动态的改变,具有很好的灵活性。

继承是在编译时就发生了的,所以无法在运行时改变,没有足够的灵活性。

由于子类会继承父类所有非私有的东西(好比爱她就接受她的一切),如果继承下来的实现不适合解决新的问题,则子类必须重写,这样最终还是限制了复用。

继承会破坏封装特性,因为继承将超类的实现细节暴露给了子类。

如果超类的实现发生改变时,那么子类的实现也会跟着发生改变。

与里氏代换原则区别

“ Is-A ”是严格的分类学意义上的定义,意思是一个类是另一个类的“一种”。而“ Has-A ”则不同,它表示某个角色拥有某一项责任。

里氏代换原则表述的是“ Is-A ”关系,而组合 / 聚合复用表述的是“ Has-A ”关系。

迪米特法则( LOD )

迪米特法则( Law of Demeter )也称最少知识原则( Least Knowledge Principle,LKP ),就是说,一个对象应该对象其他对象有最少的了解。

各种不同的表述:

1、     只与直接的朋友通信。

2、     不要跟“陌生人”说话。

3、     每个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

4、     我的知识(实现细节)你知道得越少越好。

狭义的迪米特法则

狭义的迪米特则要求一个对象仅仅与其朋友发生相互作用。

如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中的一个类需要调用另一个类的某个方法的话,可以通过第三者转换。

朋友类的定义

1、      当前对象本身( this )

2、      方法的输入输出参数中的类

3、      成员变量的直接引用对象

4、      集合成员中的元素类

5、      当前对象所创建的对象

接口隔离原则( ISP )

接口隔离原则讲的是:使用多个专门的接口比使用一个总的接口要好。换言这,从一个客户类角度来看,一个类对另外一个类的依赖性应当是建立的在最小的接口之上。

定义

Interface Segregation principle :应当为客户端提供尽可能小的单独的接口,而不要提供大的总接口,即提供职责单一的接口。

1、     客户端不应该被强迫去依赖于它们不需要的接口 。

2、     类间的 依赖关系应该建立在最小的接口上 。

第一点讲的是,客户端需要什么接口我们就提供什么接口,把不需要的接口剔除掉,那就需要对接口进行细化,保证其纯洁性。第二点其实与第一点表达的主旨是一样的,只是一个事物的两种不同描述。

与单一职责原则的不同

上面两点可以概括为一句话:建立专门的接口,不要建立臃肿庞大的接口,或更进一步讲: 接口尽量细化,同时接口中的方法尽量少 。这与单一职责原则不是相同吗?错,接口隔离原则与单一职责原则的审视角度是不相同的, 单一职责要求的是类和接口的职责单一,即功能单一,注重的是“功能”,它是从功能上的划分;而接口隔离原则是从“服务”的角度来看的,它要求的是“服务”专一,是从服务的角度来划分的 。

接口分离指的是将臃肿的接口细化,而不是建立一些无用的接口或者随意的建立接口。

时间: 2024-10-07 17:23:11

设计模式的原则 抽要理解的相关文章

深入理解设计模式六大原则

深入理解设计模式六大原则 万变不离其宗,不管是Java还是C++,凡是面向对象的编程语言,在设计上,尽管表现形式可能有所不同,但是其实质和所需遵守的原则都是一致的.本文便是带领读者去深入理解设计模式中的六大原则,以期帮助读者做出更好的设计. 单一职责原则 单一职责原则:Single Responsibility Principle,简称SRP 定义: 应该有且仅有一个原因引起类的变更. 问题场景: 类C负责两个不同的职责:职责D1,职责D2.当由于职责D1需求发生改变而需要修改类C时,有可能会导

设计模式六大原则(3)--依赖倒置原则

定义: 高层次的模块不应该依赖于低层次的模块,两者都应该依赖于抽象接口:抽象接口不应该依赖于具体实现.而具体实现则应该依赖于抽象接口.依赖倒置原则英文全称为Dependence Inversion Principle,简称为DIP. 问题由来: 类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块,负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案: 将类A修改为依赖接口I,类B和

设计模式六大原则(4)--接口隔离原则

定义: 客户端不应该依赖它不需要的接口:类之间的依赖关系应建立在最小的接口之上.接口隔离原则英文全称为Interface Segregation Principle ,简称为ISP. 个人理解: 通俗的来说,接口不能臃肿庞大,而使根据具体需要尽量的细化.接口中的方法也要尽可能的少.接口是设计对外的一种契约,通过分散定义多个接口可以预防将来变更的扩散,使得真个系统变得更加稳定和更具有可维护性. 问题由来: 类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类C不是最小的接口,那么

设计模式六大原则(4):接口隔离原则

接口隔离原则 定义:客户端不应该依赖它不需要的接口:一个类对另一个类的依赖应该建立在最小的接口上. 问题由来:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法. 解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系.也就是采用接口隔离原则. 接口隔离原则(Interface  Segregation Principle, ISP):使用多个专门的接口,而不使用单一的总接口,即客户端

设计模式六大原则(3):依赖倒置原则(转载)

设计模式六大原则(3):依赖倒置原则 定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象:抽象不应该依赖细节:细节应该依赖抽象. 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块,负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率. 依赖倒置原则

java设计模式六大原则

目录: 设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置原则 设计模式六大原则(4):接口隔离原则 设计模式六大原则(5):迪米特法则 设计模式六大原则(6):开闭原则 设计模式六大原则(1):单一职责原则 定义:不要存在多于一个导致类变更的原因.通俗的说,即一个类只负责一项职责. 问题由来:类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障. 解决方案

设计模式六大原则(6):开闭原则

开闭原则 定义:一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 问题由来:在软件的生命周期内,因为变化.升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试. 解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化. 开闭原则(Open-Closed Principle, OCP):一个软件实体应当对扩展开放,对修改关闭.即软件实体应尽量在不修改原有代码

详解设计模式六大原则

设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的:设计模式使代码编制真正工程化:设计模式是软件工程的基石脉络,如同大厦的结构一样. 借用并改编一下鲁迅老师<故乡>中的一句话,一句话概括设计模式: 希望本无所谓有,无所谓无.这正如coding的设计模式,其实coding本没有设计模式,用的人多了,也便成了设计模式 v六大原

设计模式六大原则(4):接口隔离原则(Interface Segregation Principle)

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