面向对象设计原则中SRP的示例分析

发布时间:2021-12-27 13:55:15 作者:小新
来源:亿速云 阅读:165

这篇文章主要介绍了面向对象设计原则中SRP的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

做开发到现在,相信大家已经听到过这样的说法:"类的职责越单一,越容易重用。"这话怎么理解呢?我举个例子,校验码。设想你现在拿到一个任务就是实现我们系统中的登录模块的校验码功能,你怎么做?我觉得我们大部分开发人员都会做下面这样的设计(当然更坏的是有人干脆写一个工具类,提供一个静态的generateVerifyCode方法):

面向对象设计原则中SRP的示例分析

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

细分析可以看出,导致实现类需要做修改的原因是:它承担了两个本应该分离的职责――产生随机文本和生成校验码图片。好,我们尝试将产生随机文本的职责分离出来,设计如下:

面向对象设计原则中SRP的示例分析

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

面向对象设计原则中SRP的示例分析

这样做,把图片的生成职责也单独抽象成一个演化体系,这样以来,将来如果需要在显示校验码时加上背景色或者背景噪音,只需要添加新的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抽象隔离了取得数据库链接的变化)。这个接口包含了两个职责:数据库链接管理和数据操作。       

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

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

如果让我列举一下一个良好的设计应该具备的素质,我会说:高内聚,低耦合。单一职责原则正是实现高内聚低耦合需要遵守的一个原则。

感谢你能够认真阅读完这篇文章,希望小编分享的“面向对象设计原则中SRP的示例分析”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!

推荐阅读:
  1. Java面向对象设计原则
  2. php面向对象的示例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

上一篇:python怎么处理帧数不等的视频

下一篇:Android如何自定View实现滑动验证效果

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》