***面向对象设计原则***
来源:互联网 发布:淘宝申请代付怎么取消 编辑:程序博客网 时间:2024/05/29 15:07
1.SRP(单一职责原则) 就一个类而言,应该仅有一个引起它变化的原因。一个类只能做一件事情
描述:就一个类而言,应该仅有一个引起它变化的原因。
应用:在构造对象时,将对象的不同职责分离至两个或多个类中,
确保引起该类变化的原因只有一个。
好处:提高内聚 降低耦合
缺点:造成资源文件增多,管理不便
项目举例:在我们状态模式中,每个状态都有与之相对应的行为。 这就很好的体现了单一职责原则。
SRP说的其实是类设计时的职责划分和粒度问题。
在软件开发中使用SRP原则时,一个类承担一个职责,过多互不相关的职责集中在一个类中会导致高耦合性。
但要根据具体的情况设计,避免因过度追求单一职责而将类的结构设计的过度复杂,过犹不及。
策略模式,
个人观点:该原则可以有效降低耦合,减少对不必要资源的引用。
但后果是造成源文件增多,给管理带来不便,所以在实际应用中,
可以对经常使用或经常需要改动的模块应用该原则。
2.OCP(开-闭原则) (对扩展开放,对修改关闭) 即在不修改原码的情况下对其进行扩展。
描述:"对于扩展是开放的"(Open for extension)。这意味着模块的行为是可以扩展的。
当应用的需求改变时,可以对模块进行扩展,使其具有满足改变的新行为。
也就是说,我们可以改变模 块的功能。"对于更改是封闭的"(Close for modification)。
对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。
应用:高级语言中的接口与虚拟类。
好处:提高灵活性、可重用性、可维护性
难点:OCP的关键是抽象(抽象父类或接口),创建正确的抽象花费时间和精力,
也增加了软件设计的复杂性。正确的做法是 只对程序中频繁变化的部分做出抽象,
拒绝不成熟的抽象和抽象一样重要.
OCP是OO设计原则中高层次的原则,其余的原则对OCP提供了不同程度的支持
对OCP的追求也应该适可而止,不要陷入过渡设计。
策略,装饰器,模板
个 人观点:OCP的关键是抽象,抽象的目的是创建一个固定却能够描述一组任意个可能行
为的基类。而这一组可能的行为则表现为派生类。对于基类的更改是封闭 的,所以它
里边的方法一旦确定就不能更改(对接口里的方法进行更改将带来灾难性的后果)。
模块通过抽象基类进行引用,对派生类的扩展并不影响整个模块,所 以它是开放的。
遵循OCP的代价也是昂贵的,创建正确的抽象是要花费开发时间和精力的,同时抽象也增加
了软件设计的复杂性。因此有效的预知变化是OCP设 计的要点,这需要我们进行适当的调查,
提出正确的问题,并利用我们的经验和一般常识来做出判断。正确的做法是,
只对程序中频繁变化的部分做出抽象,拒绝不 成熟的抽象和抽象本身一样重要。
3.LSP(里氏替换原则) 任何基类可以出现的地方,子类一定可以出现。反之不成立。
定义:用子类代替父类。父类能去的地方,子类也能够去。
举例:圆和椭圆,圆是椭圆的子类, 椭圆能去的地方,圆就能去,反之,则不成立。
优点:子类之间的替换非常容易。
项目举例:工厂模式就很好的实现了这一原则, 比如说dao层,父类并不知道是生成那一个子类的对象。 而我们的子类是知道它实现的是那个接口。
LSP是使OCP成为可能的主要原则之一。
正是子类型的可替换性才使得使用基类类型的模块在无需修改的情况下就可以扩展。
附A:
基于契约设计(DBC:Design By Contract)
使用DBC,类的编写者能够显式的规定针对该类的契约。客户代码的编写者可以通过该契约获悉可以依赖的行为方式。
契约是通过为每个方法声明的前置条件(preconditions)和后置条件(postconditions)来指定的。
要使一个方法得以执行,前置条件必须要为真。执行完毕后,该方法要保证后置条件为真。
附B:
use-a 依赖 A与B use-a关系 A中持有B的实例,B实例是在A之外创建,通过传参被A使用,可以调用B的方法或属性。
例如:我使用电脑。
has-a 组合 A与B has-a关系 A持有B的实例,A负责B的创建。
1.静态Has-A关系。这在UML中叫做组合(composition)
例如:我有一双手
2.动态Has-A关系。这在UML中叫做聚合(aggregation)
例如:Ant-Team拥有5名成员。
is-a 继承 A与B is-a 关系 B是A的父类
工厂模式,策略,模板,装饰器
描述:若对每个类型S的对象O1,都存在一个类型T的对象O2,
使得在所有针对T编写的程序P中,用O1替换O2后,程序P行为功能不变,则S是T的子类型。
应用:在实现继承时,子类型(subtype)必须能替换掉它们的基类型(base type)。
如果一个软件实体使用的是基类的话那么也一定适用于子类。但反过来的代换不成立。
个 人观点: LSP是使OCP成为可能的主要原则之一,对LSP的违反将导致对OCP的违反,
同时二者是OOD中抽象和多态的理论基础,在OOPL中表现为继承。
在高 级语言(JAVA、C#)中,只要我们严格按照接口和虚拟类的语法规范来做
就能很好遵循此原则,另外我们还应该避免一些更微妙的违规情况。举个例子,
正方 形和矩形,矩形可以做为正方形的基类,因为正方形也是一种矩形,但对于正方形来说,
setWidth()和setHeight()是冗余的,且容易引起错 误,这样的设计就违反了LSP原则。
如果有两个具体类A和B之间的关系违反了LSP,可以在以下两种重构方案中选择一种:
1 .创建一个新的抽象类C,作为两个具体类的超类,将A和B共同的行为移动到C中,
从而解决A和B行为不完全一致的问题。 2 .从B到A的继承关系改写为委派关系。
4.DIP(依赖倒置原则)
定义:父类不依赖于子类,抽象不依赖于细节。
项目举例:比如说dao,和dao的实现,我们dao层不应该知道dao实现的具体的操作。
如果dao层需要修改的话,那么还会影响到dao的实现,这样耦合度就非常的高。
A.高层模块不应该依赖于低层模块。它们都应该依赖于抽象。
B.抽象不应该依赖于细节,细节应当依赖于抽象
缺点:将导致大量的类文件。给维护带来不必要的麻烦。所以,正确的做法是只对程序中频繁变化的部分进行依赖倒置
附A:
启发式规则:
1.任何变量都不应该持有一个指向具体类的指针或者引用.
2.任何类都不应该从具体类派生(始于抽象,来自具体)
3.任何方法都不应该覆写它的任何基类中的已经实现了的方法.
这个原则对于那些虽然具体但是却稳定的类来说似乎并不是很合适, 如果一个类不太会改变,
而且也不太可能创建其他的派生类,那么依赖它似乎并没有太大的危害。比如java的String类。
DIP的关键其实在于找到系统中“变”与“不变”的部分,并利用接口将其隔离。
附B:
IoC就是Inversion of Control,控制反转。
在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制。这称为控制反转。
模板模式
5.ISP(接口隔离)
定义:不要强迫客户依赖于它们不用的方法。 让一个类对另外一个类的依赖性应当是建立在最小的接口上的。
好处:避免接口污染。
项目举例:如果我们一个类需要一些方法,避免实现方法过多的接口。
使用多个专门的接口比使用单一的总接口要好。
一个类对另外一个类的依赖性应当是建立在最小的接口上的。
一个接口代表一个角色,不应当将不同的角色都交给一个接口。
没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。
观察者模式
6.LKP(最少知识原则) 又叫迪米特法则(Law of Demeter),LoD
一个对象应当对其他对象有尽可能少的了解,不和陌生人说话
这是一个关于如何松耦合(Loosely-Coupled)的法则
优点:代码安全性。
项目举例:我们在程序中通常把能私有化的属性,方法,都要尽量的私有化。 这样我们修改一些模板对其他模板的影响就少些,使代码也更加安全。
门面模式就是隐藏子系统的复杂性。与客户程序打交道只有一个类而已。
缺点:
在系统里造出大量的小方法,这些方法仅仅是传递间接的调用,与系统的商务逻辑无关
用迪米特法则到系统的设计中时,要注意以下几点:
* 在类的划分上,应当创建有弱耦合的类.类之间的耦合越弱,就越有利于复用.
* 在类的结构设计上,每一个类都应当尽量降低成员的访问权限.
* 在类的设计上,只要可能,一个类应当设计成不变类.
* 在对其他类的引用上,一个对象对其他对象的引用应降到最低.
* 尽量限制局部变量的有效范围.
门面模式
米特法则又叫作最少知识原则(Least Knowledge Principle或简写为LKP),就是说一个对象应当对其他对象有尽可能少的了解。
如何实现迪米特法则
迪米特法则的主要用意是控制信息的过载,在将其运用到系统设计中应注意以下几点:
1) 在类的划分上,应当创建有弱耦合的类。类之间的耦合越弱,就越有利于复用。
2) 在类的结构设计上,每一个类都应当尽量降低成员的访问权限。一个类不应当public自己的属性,而应当提供取值和赋值的方法让外界间接访问自己的属性。
3) 在类的设计上,只要有可能,一个类应当设计成不变类。
4) 在对其它对象的引用上,一个类对其它对象的引用应该降到最低。
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 基于sinox的汉澳现代战争军事指挥作战系统
- Asp.net页面中给DropDownList赋值
- 堆和栈的区别(转)
- const 的主要用法
- Treap树非递归插入
- ***面向对象设计原则***
- 北京答辩归来
- cg的输入/输出与语义绑定
- 邮件接收
- VI
- C#基础
- 受刺激了,看来有必要继续写博了!
- I2C协议
- 通过反汇编代码解读指针和引用的内在机理