设计模式原则

 

OO 基础

  抽象

  封装

  多态

  继承

 

OO 原则

1 找出应用中可能需要变化指出,把它们独立出来,不要和那些不需要变化的代码混在一起;

2 针对接口编程,而不是针对实现编程;

3 多用组合,少用继承。

4 类应该对扩展开放,对修改关闭。

5 为交互对象之间的松耦合设计而努力。

6   依赖抽象,不要依赖具体类。

7 只和朋友交谈。

8 别找我,我会找你。

9 类应该只有一个改变的理由。

 

设计原则是设计模式的灵魂。

三大基本面向对象设计原则:               

1. 针对接口编程,而不是针对实现编程  

2. 优先使用对象组全,而不是类继承;

3. 封装变化点。

下面开始学习常用的具体的一些设计模式原则:

1. 单一职责原则( SRP

单一职责原则( SRP ),就一个类而言,应该仅有一个引起它变化的原因。 也就是说,不要把变化原因各不相同的职责放在一起,因为不同的变化会影响到不相干的职责。再通俗一点地说就是,不该你管的事情你不要管,管好自己的事情就可以了,多管闲事害了自己也害了别人。

在软件设计中,如果一个类承担的职责过多,就等于把这些职责耦合在一起,而一个职责的变化可能会削弱和抑制这个类完成其他职责的能力。这耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。

软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。如果多于一个的动机去改变一个类,那么这个类就具有多余一个的职责,就应该要考虑类的职责分离。

这个原则实质上是对于一个类的粒度划分作出了一个规定。一个具备强大功能的庞大类并不是一个好的做法,不如将其分割成多个小类,每个小类仅提供某个单一的功能,这样我们的编码和测试都会简化,避免了因为复杂而造成潜在的错误,然后使用 Facade 或者 Adapter 模式对外提供一个聚合的操作接口就可以了。

2 . 开放 - 封闭原则( The Open-Closed Principle 简称 OCP

开放 - 封闭原则,或叫开 - 闭原则,是说软件实体 ( 类、模块、函数等 ) 应该是可以扩展的,但是不可修改。 不修改的意思就是是“你可以随便增加新的类,但是不要修改原来的类”。从这个角度去理解就好多了,其实这里还是一个隔离变化的问题。

这个原则的两个特征:一个是对于扩展是开放的;另一个是对于更改是封闭的。

我们在设计开发任何系统时,都不可能指望系统一开始就需求确定,就不再变化(要这样就太幸福了,哈哈),这是不现实的也是不科学的想法。既然需求是有一定变化的,那么如何在面对需求变化时,设计的程序可以相对容易的修改,不至于说,新需求一来,就要把整个程序推倒重来 ( 这样会让程序员疯了不可,哈哈,你不想疯吧 ) 。怎样的设计才能面对需求的改变却可以保持相对稳定,从而使得系统可以在第一个版本以后不断推出的新版本呢?开放 - 封闭原则就是我们的答案。

在程序设计时,我们要时刻考虑尽量把类设计的足够好,写好了就不要去修改,如果有新的需求来了,我们增加一些类来完成新的需求,原来的代码能不动就不动。

绝对的对修改关闭是不可能的,无论模块是多么的封闭,都会存在一些无法对之封闭的变化,既然不能完全封闭,设计人员必须对他设计的模块应该对那种变化封闭做出抉择、他必须事先猜测出最有可能发生变化的变化种类,然后构建抽象来隔离那些变化。

开放 - 封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所生成的巨大好处,也就是可维护、可扩展、可复用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的部分都做出抽象,然后,对于应用程序中的每部分都刻意定进行抽象同样不是一个好主意,拒绝不成熟的抽象和抽象本身一样重要。

这个原则一般通过抽象和多态来体现其机制。我们通过抽象基类或接口来提供一个标准调用规范,每个实质子类都继承或者实现这个规范以达到不同的应用操作。在实际使用中我们一般通过工厂模式 (Abstract Factory / Factory Method / Simple Factory) 来到到可扩展而不修改现有代码的目的。

3. 依赖倒转原则

依赖倒转原则:抽象不应该依赖于细节。细节应该依赖于抽象;高层不应该依赖于底层,两者都应该依赖于抽象。 说白了就是要针对接口编程,不要针对实现编程。抽象的东西才是最稳定的,也就是说,我们依赖的是它的稳定。 传递参数,或者在组合聚合关系中,尽量引用层次高的类。

依赖倒转其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写是考虑的都是如何针对抽象编程而不是针对细节编程,即程序中的所有的依赖关系都是终止与抽象类或者接口,那就是面向对象的设计,反之就是过程化设计了。

高层模块一般是指那些实现业务规则的单元,而所谓低层模块是具体的一些功能代码。我们在设计的时候,一般高层模块会直接依赖于低层模块来实现其具体功能,这势必会造成相关干扰,任何一个模块的修改都会影响其关联的模块。因此 DIP 原则建议我们在两个模块之间添加一个抽象,两者通过依赖和实现抽象来达到沟通和调用,从而确保在抽象不变动的情况下,各自隔离而互不影响。抽象本身应该是个干净的协议,它具备完整的独立性,如果依赖于某个功能细节,那么抽象本身就变成不稳定因素,造成以后修改的污染。

4. 里氏代换原则

里氏代换原则( LSP ):子类型必须能够替换掉他的父类型。 说白了就是一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而他察觉不出父类对象和子类对象的区别,也就是说,在软件里面,把父类都替换成他的子类,程序行为没有变化。

有了里氏替换原则,才是继承服用成为可能,只有当子类可以替换掉父类时,软件的功能不受到影响,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。

有了里氏代换原则,才能使开放 - 封闭原则成为可能,正是由于子类型的可替换性才使得父类型的模块在无需修改的情况下扩展。

这个原则实质上就是多态的一种体现,子类继承或者覆盖基类的方法,具有和基类完全相同的调用规范。

5 . 接口隔离原则 (ISP)

接口隔离原则 (ISP): 不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。 这个说得很明白了,再通俗点说,不要强迫客户使用它们不用的方法,如果强迫用户使用它们不使用的方法,那么这些客户就会面临由于这些不使用的方法的改变所带来的改变。

很多时候我们设计的一个类会提供给多个客户调用,那么势必造成客户会 看到 一些他们根本用不上的方法,这对于客户是一种干扰,会加大他们的负担,甚至造成错误调用而影响系统的功能实现。在 C# 中我们可以继承多个接口,每个客户只使用其特定的接口,更具体一点,我们返回给客户的是一个接口,而不是一个类实例来达到接口隔离。在类编码中可能还会用到接口方法这个概念。

6. 迪米特法则( LoD

迪米特法则( Law of Demeter 或简写 LoD )又叫最少知识原则( Least Knowledge Principle 或简写为 LKP : 如果两个类不彼此之间直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某个方法的话,可以通过第三者转发这个调用。

      迪米特法则首先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限。

     迪米特法则其根本思想强调的是类之间的松耦合。类之间的耦合越弱,越利于复用,一个处于弱耦合的类被修改,不会对有关系的类造成波及。

7. 合成 / 聚合复用原则( Composite/Aggregate Reuse Principle CARP

聚合是一种弱的“拥有”关系,体现的是 A 对象可以包含 B 对象,而 B 对象不是 A 对象的一部分。例如:雁群和大雁。

合成是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。例如:鸟和翅膀。

依赖 是比 关联 弱的关系, 例如:   
   
若类 A 单向关联指向类 B ,则在类 A 中存在一个属性 B   b   
   
若类 A 依赖类 B ,则不会有这个属性,类 B 的实例可能存在于某个方法调用的参数中,或某个方法的局部变量中。

合成 / 聚合复用原则( Composite/Aggregate Reuse Principle CARP ):经常又叫做合成复用原则( Composite Reuse Principle CRP ),就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新对象通过向这些对象的委派达到复用已有功能的目的。 说白了就是要尽量使用合成 / 聚合,尽量不要使用继承。

 

  推荐网站:好巴鹿(http:// www.haobalu.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值