`
ohmygodlzl
  • 浏览: 21408 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

OOD之单一职责原则

阅读更多
这个系列是早前发布在部门wiki上的,引导组里的兄弟入门OOD,希望同样对刚刚走到OOD门前的同学有用。


    一直想跟同志们探讨一下面向对象设计(OOD)的原则问题,但因为自己理解有限,怕说不好误人子弟,一直就没开始。现在想做个尝试,从浅处说起,便于理解,也希望能对我们日常的开发起到帮助。
    我们做软件开发,要做的事情无非就是:拿到一份需求,通过一系列步骤把它转化为可运行的系统。这些步骤简单的说就是需求分析――>面向对象分析(包括领域建模)――>架构设计――>详细设计――>编码――>测试――>发布这样的过程,其中架构设计和详细设计中都要用到OOD的一些原则。说起面向对象,一般大家都会想到封装,继承,多态,这是面向对象的特征,还不是原则,我想说的原则是Robert C. Martin在他的《敏捷软件开发-原则模式和实践》中提到的原则。今天聊聊单一职责原则(SRP)。
    做开发到现在,相信大家已经听到过这样的说法:"类的职责越单一,越容易重用。"这话怎么理解呢?我举个例子,校验码。设想你现在拿到一个任务就是实现我们系统中的登录模块的校验码功能,你怎么做?我觉得我们大部分开发人员都会做下面这样的设计(当然更坏的是有人干脆写一个工具类,提供一个静态的generateVerifyCode方法):



    这个设计有什么问题呢?有接口有实现,貌似够合理了。我们拿实际发生的事来看够不够合理――我们系统刚上线的时候校验码的实现没有现在这样花哨,那个时候只是白色背景加上一组没有经过扭曲处理的数字;但是后来需求进化了,因为原来的校验码可能会被破译,所以需要对数字进行扭曲,而且不能只产生数字,还要有字母,以增加破译的难度。这时我们怎么办?基于上面的设计,就需要修改VerifyCodeGeneratorImpl类(注意:即使在这种不合理的设计下,修改实现也是不好的做法,倒不如丢弃这个实现,新增一个实现),修改其中产生随机数的代码,并且在生成图片的时候对产生的随机文本添加扭曲处理逻辑。因为需求的变化而修改代码, 这说明原来的设计是不好的,违反了面向对象设计的另外一个原则"开放封闭原则(OCP)",这个原则另外再谈,主要就是说一个类(或者模块)只可以扩展,但不可修改。
    细分析可以看出,导致实现类需要做修改的原因是:它承担了两个本应该分离的职责――产生随机文本和生成校验码图片。好,我们尝试将产生随机文本的职责分离出来,设计如下:



   在这样的设计下, 校验码随机文本的生成职责被分离成一个单独的演化体系,随着需求的变化可以添加产生汉字随机文本之类的新实现,并且不影响校验码的显示。但这个设计还没有满足需求的变更,因为现在的需求是不光随机文本内容从纯数字变成了数字加字母,而且要求显示的时候对数字进行扭曲,在这个设计中,我们可以添加新的VerifyCodeGenerator实现如TransformedVerifyCodeGeneratorImpl以替换原来的VerifyCodeGeneratorImpl。这样做可行,但还有更好点的设计,如下:



     这样做,把图片的生成职责也单独抽象成一个演化体系,这样以来,将来如果需要在显示校验码时加上背景色或者背景噪音,只需要添加新的ImageGenerator实现。而且ImageGenerator作为一个通用的类,可以被其他有相应生成图片需求的类所重用而不是只局限于生成校验码。上面的设计配合Spring的依赖注入,我们可以生成N * M种校验码(N是RandomTextGenerator的实现类数,M是ImageGenerator的实现类数),而基于最初的设计,我们就需要创建N*M个VerifyCodeGenerator的实现类,且这些实现类可复用性很低。   
    从上面例子的探讨中可以得出这么一个结论:一个类(或者大到模块,小到方法)承担的职责越多,它被复用的可能性越小。这就是单一职责原则(SRP)要表述的内容:就一个类而言,应该仅有一个引起它变化的原因。    
    本着这个原则,我们再看一个常见的DAO设计:

interface DAO{

    Connection connect();

    void close();

    void executeUpdate();

    ResultSet executeQuery(String sql);
}
    这个接口有什么问题没有,好像很多人都这么干。只要设想一下如果底层数据库变化了,connect方法的代码就可能需要改变(有人说我们不需要改变,那是因为我们使用了Spring提供的DataSource抽象隔离了取得数据库链接的变化)。这个接口包含了两个职责:数据库链接管理和数据操作。       

    在实际操作中,如何识别职责是一个说起来容易做起来难的问题,比如有人可能会说,"产生校验码图片"本身就是一个独立职责呀,我说是的,如果我们的校验码图片一成不变,最初的那个设计不算很坏,只不过丧失了一点重用性而已(比如产生随机文本的逻辑可能被其他的模块重用),但是需求后来变化了,不能只显示数字,还要字母,这说明产生随机文本是一个变化纬度,将来很可能还有新的变化,那就应该把这个职责独立出来;需求又说显示的文本需要扭曲,这说明图片的生成也是一个变化纬度,沿着这个纬度将来很可能也有新的变化,那就也应该把这个职责独立出来。需求变化所影响的变化纬度,往往就是应该被独立的职责。所以如果你接到一个需求后发现需要修改一个已经存在的类,那就要考虑一下是不是原来的设计不合理,没有把应该独立出来的职责分离出来。需求变化结合经验、常识,就可以慢慢识别职责应该分到什么粒度了。       

    单一职责原则不光对类设计有意义,对以模块、子系统为单位的架构设计一样有意义,一个模块、子系统也应该仅有一个引起它变化的原因,不同的是模块和子系统承担的职责粒度跟类相比是另外一个层次了。       

    如果让我列举一下一个良好的设计应该具备的素质,我会说:高内聚,低耦合。单一职责原则正是实现高内聚低耦合需要遵守的一个原则。
  • 大小: 8.9 KB
  • 大小: 26.3 KB
  • 大小: 43.2 KB
1
0
分享到:
评论

相关推荐

    OOD设计基本原则整理.doc

    OOD 设计基本原则之二:单一职责原则 单一职责原则是 OOD 设计的另一重要原则,该原则强调一个类或接口应该仅有一个引起变化的原因。职责可以理解为“变化的原因”。如果能够想到多于一个的原因去改变一个类,那么...

    6单一职责原则-MOOC课程内容.pdf

    单一职责原则(Single Responsibility Principle,简称SRP)是面向对象设计(OOD)中的一个基本原则。它强调每个类应该只有一个改变的理由,意味着一个类应该只有一个职责,只有一个因素能引起这个类的变更。当类...

    OOD设计基本原则 面向对象设计必备

    OOD 设计基本原则包括 OCP 原则、里氏替换原则、依赖倒置原则、接口隔离原则、聚合与继承原则、单一职责原则、Separation of concerns Principle 和 Pareto Principle 等。 OCP 原则(Open-Closed Principle)是 ...

    软件设计的七大原则(OOD)

    其中包括SRP(单一职责原则)、OCP(开闭原则)、LSP(里氏替换原则)、ISP(接口分离原则)、DIP(依赖倒置原则)、CRP(组合/聚合复用原则)和PLK(最小知识原则)。 一、SRP(Single Responsibility Principle)...

    面向对象设计OOD 面向对象设计OOD

    OOD 的核心是面向对象设计原则(OOD principles),其中包括单一职责原则(SRP)、开闭原则(OCP)、Liskov 替换原则(LSP)、基于契约设计(DBC)等。 单一职责原则(SRP) 单一职责原则是指一个类应该只有一个...

    如何解释OOD及设计

    在这一阶段,应该遵循面向对象的原则,如单一职责原则、开放封闭原则等,以确保代码的质量。 7. **测试与迭代**:对软件进行测试,验证其功能和性能是否符合预期。根据测试结果进行必要的调整和优化。 8. **文档...

    c# OOP/OOD

    1. **SOLID原则**:SOLID是五个面向对象设计原则的首字母缩写,包括单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则指导我们编写可维护、可扩展的代码。 2. **设计模式**:设计模式是...

    OOD原则 GRASP GOF

    1. **单一职责原则(Single Responsibility Principle, SRP)**: 一个类或对象应该只有一个引起它变化的原因。这意味着每个类都应有一个明确且单一的职责,避免职责混杂导致代码耦合度过高。 2. **开闭原则(Open...

    c++ 面向对象设计五大原则

    1.单一职责原则(Single Resposibility Principle,SRP) 专注是一个人的优良品质,同样,单一职责也是一个类的优良设计。单一职责的核心思想:一个类只做好一件事情。 单一职责原则可以看作是高内聚、低耦合在面向...

    OOD.rar_ood

    7. **原则与指导方针**:OOD遵循一些基本原则,如 SOLID 原则,包括单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)和依赖倒置原则(DIP)。这些原则有助于创建易于理解和维护的...

    OOD启思录(高清)

    8. ** SOLID原则**:SOLID是面向对象设计的五个基本原则,包括单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)和依赖倒置原则(DIP)。这些原则指导我们编写易于维护和扩展的代码...

    OOD启思录-面向对象圣典(英文版)

    《OOD启思录—面向对象圣典》是一本深入探讨面向对象设计(OOD)改进之道的专业书籍。作者通过一系列指导原则帮助读者理解如何提升软件设计的完整性与效率。书中提供了超过六十条跨语言的设计指南,这些指南并非刻板的...

    Uncle Bob OOD Principles

    1. **单一职责原则(Single Responsibility Principle, SRP)**:每个类或模块应该只有一个改变的原因。这意味着一个类应专注于一个特定的功能,而不是承载多个不相关的职责。这样可以提高代码的可维护性和可测试性...

    OOA、OOD和UML

    4. **设计原则**:如单一职责原则、开放封闭原则、里氏替换原则、依赖倒置原则等,它们指导良好的设计实践。 5. **设计模式**:如工厂模式、单例模式、观察者模式等,它们是解决常见设计问题的通用解决方案。 6. **...

    2018年最新 OOD面向对象设计专题班.zip

    类的定义应遵循单一职责原则,即一个类只做一件事情,这样可以提高代码的可读性和可维护性。接口是另一种重要的设计元素,它定义了一组方法,但不包含具体的实现,用于规范类的行为。 OOD中的设计模式是解决常见...

    面向对象七大基本设计原则.pdf

    1. 单一职责原则(Single Responsibility Principle, SRP):一个类应该只有一个引起它变化的原因,即一个类只负责一项任务。该原则强调一个类应该只有一个功能点。 2. 开闭原则(Open/Closed Principle, OCP):...

    ood启思录读书笔记

    - **减少类的协作对象**:一个类的职责应当尽可能单一,与之协作的对象数量不宜过多,否则会增加类间的耦合度,降低系统的可维护性和扩展性。 - **方法与数据成员的协调使用**:类中大多数方法应在大多数情况下使用...

    面向对象的设计原则详解

    1. 单一职责原则(Single Responsibility Principle, SRP): 这个原则要求每个类只负责一个职责或功能,避免类因为承担过多职责而导致复杂性增加。当一个类承担多个职责时,一个职责的变化可能会迫使其他职责的...

    99丨总结回顾:在实际软件开发中常用的设计思想、原则和模式1

    例如,单一职责原则有助于类职责的合理划分,开闭原则可以指导我们如何设计可扩展的系统,而依赖倒置原则则常用于框架设计,通过依赖注入实现松耦合。 总的来说,理解并熟练应用这些设计思想、原则和模式,能够显著...

    ood-solid:面向对象设计的SOLID原理

    这五条原则分别是单一职责原则(Single Responsibility Principle, SRP)、开闭原则(Open-Closed Principle, OCP)、里氏替换原则(Liskov Substitution Principle, LSP)、接口隔离原则(Interface Segregation ...

Global site tag (gtag.js) - Google Analytics