Bob大叔观OO原则

上篇总结了经典的23种 设计模式,详细的解读后期会陆续的详细揭开。使用设计模式的根本原因就是为了增强代码的复用性和可维护性。而面向对象是实现代码复用的有效途径,所以这里有必要了解一下OO的基本思想和原则。

面向对象设计的原则(OOD&OOP)主要分为两大类,一类是面向类的,另一类是面向包的。设计模式基本都是围绕面向类的几个原则的实践,而面向包的几个原则主要体现在架构模式中。

S.O.L.I.D

Bob大叔(Robert C. Martin)的大名如雷贯耳,相信大部分在进击中的开发者都有阅读过经典著作《敏捷软件开发》的经历,受益匪浅。

在面向对象的程序的设计和开发过程中时,有5个原则非常重要,此外还有一个法则我们应该尽量去遵守它。

1、单一职责原则(SRP,The Single Responsibility Principle)
2、开放封闭原则(OCP,The Open Closed Principle)
3、里氏替换原则(LSP,The Liskov Substitution Principle)
4、依赖倒置原则(DIP,The Dependency Inversion Principle)
5、接口分离原则(ISP,The Interface Segregation Principle)
6、迪米特法则(LoD,The Law of Demeter、LKP)

SRP

A class should have only one reason to change.
一个类应该仅有一个引起它变化的原因。

SRP是所有原则中最简单的一个,概念简洁易懂。但却也是最难正确运用,或者说是最容易过度使用的原则。

一方面,因为SRP把职责定义成了变化的原因,如果我们能够找到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责。比如开发者经常会习惯性的把职责归类式的结合在一起,而正确的做法是发现职责并把这些职责相互分离。

另一方面,如果程序的变化方式总是导致N个职责(N>1)同时变化,那么就没必要分离它们了。在这里有一个推论:仅当变化发生时,变化的轴线才具有实际的意义。在实际的设计和开发过程中,一定要把握好分离“单个”职责的度,所谓过犹不及,过度的分离只能适得其反,违背了面向对象的封装思想。

OCP

Software entities(classes,modules,functions,etc.) should be open for extension, but closed for modification.
软件实体(如类、模块、函数等)应该对扩展开放,对修改关闭。

OCP是整个面向对象设计的核心。它代表了灵活性、可重用性和可维护性。

乍一看,两个特征似乎有所矛盾,扩展模块的功能通常是以修改模块的源代码作为手段。但是,我们有“抽象”!通过创建稳定的但又能描述一组任意个可能行为的抽象基类,并将具体的行为实现为派生类,这种做法能很好的解决开放扩展的问题。主要是针对软件中频繁变化的那部分作出合理的抽象。

当然,创建和使用抽象会增加软件复杂性和团队的精力,所以肆意的进行抽象显然并不是一个好设计,简直是折磨人。除非你有强大的智商优越感,但是面对广大平凡质朴的程序员,还请手下留情。

拒绝不成熟的抽象和抽象本身一样重要。

LSP

Derived types must be completely substitutable for their base types.
子类型必须能够完全的替换掉它们的基类型。

LSP是使OCP成为可能的主要原则之一,也是继承层次特征的主要设计原则。

一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。也就是说,在软件中,把父类都替换成它的子类,程序行为没有或者不发生变化。也就是说,只有当子类可以替换掉父类,软件的功能不受到影响时,父类才能真正的被复用,而子类也能够真正的在父类的基础上增加新的行为。

子类型的可替换性使得使用基类型表示的模块在无需修改的情况下就可以扩展。可替换性可以通过显示或者隐式的契约来定义。

DIP

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
高层模块不应该依赖于低层模块,两者都应该依赖于抽象
B. Abstractions should not depend on details. Details should depend on abstractions.
抽象不应该依赖于细节,细节应该依赖于抽象

DIP是面向对象设计的标志。

依赖倒置原则是实现许多面向对象技术所宣称的好处的基本低层机制,他的正确应用对于创建可重用的框架来说是必须的。同时它对于构建在变化面前富有弹性的代码也是非常重要的,由于抽象和细节彼此隔离,所以代码也非常容易维护。

针对接口编程,而不要对实现编程。倒置接口的所有权。


LSP和DIP乍一看还有点相似,其实,他们还是有区别的:

两个原则所站的角度不同。LSP是站在模式对象的角度,而DIP则是站在客户端程序的角度;模式对象一方将“相对多变的”子类视同它的接口(或父类),而客户程序依赖的内容是“相对稳定”的接口。


ISP

Clients should not be forced to depend upon interfaces that they don't use.
不应该强迫客户程序依赖并未使用的接口。

ISP有效的降低了程序间的耦合性,提高了程序集的内聚性。避免了接口污染。

客户程序应该仅仅依赖于他们实际调用的方法。分离客户就是分离接口。通常我们可以使用委托或者使用多重继承来分离接口。

接口隔离原则不是单纯的多余或是不多余,从设计的角度来衡量,它要依据业务领域的需要判断倒是是否真的“多余”,确保在每个领域背景下贯彻不去依赖用不到的方法。通过把胖类的接口分解为多个特定于客户程序的接口,可以实现这个目标。有效的解除了客户程序和它们没有调用到的方法间的依赖关系。

客户程序看到的应该是多个具有内聚接口的抽象基类。

LoD(LKP)

A. Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。
B. Each unit should only talk to its friends; don't talk to strangers.
C. Only talk to your immediate friends.

迪米特法则又称为最少知识原则。主要有三层意思,就是让调用者对于目标对象的知识最少,而且只和你的直接朋友对话,千万不要和陌生人说话。

该法则因在《程序员的修炼之道》一书中提及而声名鹊起广为人知。其初衷在于降低类之间的耦合,但是由于通过友元类来建立一个类和其他类的联系,或是减少对其他类的依赖,这导致了在一定程度上增加了系统的复杂度。

小结

这些原则是数十年软件工程经验来之不易的结果。是众多开发人员和研究人员思想和著作的结晶。我们应该牢记面向对象设计的原则,理解OO的设计思路。因为它们有助于开发人员消除拙劣的设计和代码臭味,并能有效的帮助开发人员构建出最适合于当前特性集的设计。

Bob大叔建议:在日常工作中,只有当出现“臭味”时我们才会去使用它,如果只是因为它是一个原则就无条件的遵循它那是错误的,过分的遵循这些原则会导致不必要的复杂性和设计臭味。

个人认为,一切均应切合实际,要考虑到团队的承受能力,项目的可控范围等等因素。

不要把它当作可以在系统中随意喷洒的香水!

结尾:上面主要记述了面向类(对象)的几个设计模式原则,后续会论述面向包设计的架构模式原则 。

 
分类: 敏捷开发

Bob大叔观OO原则的更多相关文章

  1. 跟Bob大叔观OO原则

    上篇总结了经典的23种 设计模式,详细的解读后期会陆续的详细揭开.使用设计模式的根本原因就是为了增强代码的复用性和可维护性.而面向对象是实现代码复用的有效途径,所以这里有必要了解一下OO的基本思想和原 ...

  2. [翻译]Bob大叔:反思极限编程

    译者注: Bob大叔14年后再次谈论极限编程.极限编程经历了14年的风风雨雨后,Bob大叔将会给它怎么样的定义那? 在我手中拿着的一本白皮薄书,在14年前彻底的改变了软件世界.这本书的标题是解析极限编 ...

  3. oo原则

    基本原则: 封装变化Encapsulate what varies. 面向接口编程而非实现 Code to an interface rather than to an implementation. ...

  4. OO原则汇总

    SOLID原则:http://www.cnblogs.com/lanxuezaipiao/archive/2013/06/09/3128665.html https://www.cnblogs.com ...

  5. 对OO原则的个人理解

    1.单一职责原则.(Single Responsibility Principle) 注解:社会化大生产分工要细.具体每个人最好只做一件事(不要一人兼多职),这样如果这个人请假或辞职,对生产不会产生影 ...

  6. 翻译 | The Principles of OOD 面向对象设计原则

    本文首发于vivo互联网技术微信公众号 https://mp.weixin.qq.com/s/Q_pziBUhKRywafKeY2T7YQ 作者:Robert C. Martin 翻译:张硕 本文由来 ...

  7. OO之美2

    面向对象并没有想象中那么神秘,以生活的现实眼光来看更是如此.把面向对象深度浓缩起来,可以概括为: ⑴目标:重用,扩展,兼容 ⑵核心:低耦合,高内聚 ⑶手段:封装变化 ⑷思想:面向接口编程,面向抽象编程 ...

  8. 老调重弹--面向对象设计原则--S.O.L.I.D设计原则

    SRP - 单一职责原则 全称:Single Responsibility Principle 定义:每一个上下文对象(类.函数.变量等等)的定义应该仅仅包含单一的职责 描述:对象提供单一职责的高度封 ...

  9. S.O.L.I.D五大原则之单一职责SRP

    转自 : 汤姆大叔的blog Bob大叔提出并发扬了S.O.L.I.D五大原则,用来更好地进行面向对象编程,五大原则分别是: The Single Responsibility Principle(单 ...

随机推荐

  1. openGL点精灵PointSprite具体解释: 纹理映射,旋转,缩放,移动

    第一,什么是点精灵 openGL的图形由顶点构成,以后利用顶点进行纹理的映射.点精灵就是,一个顶点被当作一个精灵来处理.特别之处就是,一个顶点也可进行纹理贴出.比如,原来是个顶点构成的一个矩形,如今一 ...

  2. C++传递函数指针

    函数指针是一个很好的类型.因此,您可以编写一个函数,它的一个参数是一个函数指针.然后.在(外部)当函数使用的函数指针参数,来间接调用时调用相应的参数的函数的函数. 因为指针在不同的情况下能够指向不同的 ...

  3. Bestcoder Round#45

    1001 给定数n,要我们求该数的二进制中有多少组1, 相邻的1称为1组, 直接位运算摸你即可 #include <stdio.h> #include <string.h> # ...

  4. Windows Phone开发(15):资源

    原文:Windows Phone开发(15):资源 活字印刷术是我国"四大发明"之一,毕昇在发明活字印刷术之后,他很快发现一个问题,随着要印刷资料的不断增加,要用到的汉字数目越来越 ...

  5. 原创游戏,金庸群侠传X 0.5公布

    首先说一下背景,我个人从小特别爱玩游戏,对小时候一款游戏<金庸群侠传>DOS版更是情有独钟,自己工作以后,利用业余时间自己整了一个原创的改编版丢网上(找图片.音乐.写剧情更是虐心之极,耗时 ...

  6. 阶乘因式分解(一)(南阳oj56)

    阶乘因式分解(一) 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描写叙述 给定两个数m,n,当中m是一个素数. 将n(0<=n<=10000)的阶乘分解质因数, ...

  7. FastDFS源代码分析之tracker协议分析

    本篇博客主要解说fastdfs中tracker协议的解说. fastdfs主要是存储文件.直接把整个文件存储到磁盘上,所以.简单直接.可是也有非常大的局限性. 因此,fastdfs对文件的文件夹设置和 ...

  8. WinForm 国际化开发一例

    1.新建一个WinForm程序(在中文版的Windows下),如下,添加1个Button和1个Label 设置Form1的localizable属性为True(Form1的properties里的De ...

  9. WIZnet通过启动在线培训活动:计算机网络TCP/IP协议而事实上,现在的方法

    为了给大家营造更好的学习环境.WIZnet特此举办第一期培训活动,由WIZnet一线project师为你分享最最前沿和有用的网络技术知识,帮你解答开发过程中的疑问.欢迎前来交流.名额有限(20名满), ...

  10. C++结构体之统计最高最低分

    [Submit][Status][Web Board] Description 输入学生的姓名和成绩,统计出最高分的学生和最低分的学生. Input 输入5个学生的姓名和分数,用结构体完成 Outpu ...