文档章节

单一职责原则

Demens
 Demens
发布于 2017/07/27 15:01
字数 1036
阅读 7
收藏 0

定义:

      该原则规定每个类都应该只有一个单一的功能,并且该功能应该由这个类完全封装起来。

何为职责?

      

既然是单一“职责”,那么职责即为被规定的因素。

  • 概括:"功能(职责)"为改变的原因,一个类或者模块应该有且只有一个改变的原因。

 

例子一:

  • 如下图农活责任所示,耕菜地和耕水田即为牛和耕地机的职责,即为这个对象存在的原因(下面将来讨论这个关系图)。

 

                                       

 

看上图农活责任,晃眼一看我们会决定这是对的!但仔细一分析农活接口其中包含的耕菜地和耕水田两个责任。

  • 牛耕水田,但它耕不动菜地,只能调用耕水田的接口,因此耕菜地的接口对于牛来说就是多余的。但耕地机即能耕菜地,也能耕水田。这就像是牛本来是耕田的,我们却说它还能去耕菜地,耕地机能做的事情,老牛表示无能为力!

  • 这样违反了SRP,导致了严重的问题。因为我们给牛保留了一个多余而不会完成的责任,这让我们每次提到牛不仅说它能耕水田还能耕菜地。这让我们对牛的描述更加的复杂而没有准确性。程序也时这样,当没用的责任增加,就会让相应的类都变得臃肿腐臭。当我们要添加牛要耕后要吃草,耕地机耕地后要加油时,继续往农活接口中添加,这样使得农活什么都能干,使得后期修改维护等难度太大。

  • 如果不分离责任,在不断变化和添加的需求面前,责任之间耦合度强导致我们的程序更加的脆弱

                                                 
如上图将两个责任分离,牛实现耕水田的时候,不会知道也不会去在意耕菜地,分离了责任,该做的才做,不做的不用管。

例子二:

      电话这玩意,是现代人都离不开的。电话通话的时候有四个过程发生:拨号、通话、回应、挂机。如下面的接口代码:

interface IPhone {
  void dial(String pno);//拨号
  void chat(Object o);//发送消息
  void hangup();//挂断
}

       大家看下这个接口有没有问题?我相信大部分读者都会说没有问题呀,我就是这么做的呀。是的,这个接口几乎没有问题。但是,单一职责原则要求一个接口或类只有一个原因引起变化,也就是一个接口或类只有一个职责。

       这个接口中显示了两个职责,一个是连接管理,一个是数据通信。dial和hangup函数进行调制解调器的连接处理,而chat函数进行数据的通信。

这两个责任应该被分开吗?这决定于应用程序以何种方式变化。如果应用程序的变化会影响连接函数的部署,那么这个设计就具有僵化性的臭味。因为调用send和recv的类必须要重新编译连接处理函数,部署的次数常常会超过我们希望的次数。在这种情况下,这两个职责应该被分离。如图下图所示,这样避免了客户应用程序和这两个职责耦合在一起。

       如果应用程序的变化方式总是会导致两个职责同时变化,那么就不必分离他们,分离后会导致不必要的复杂性。

总结

  • SRP为最简单的原则,也是最难运用好的原则
  • 软件设计真正要做的其实就是发现责任并把那些责任分离
  • 其他原则都将能追溯到SRP
  • 大道至简,只有不断在代码中运用才能真正体会其中的奥妙

 

参考

[1]《设计模式之》第1章 单一职责原则

© 著作权归作者所有

上一篇: 里氏替换原则
下一篇: Java泛型详解
Demens
粉丝 0
博文 11
码字总数 14760
作品 0
私信 提问

暂无文章

Spring使用ThreadPoolTaskExecutor自定义线程池及实现异步调用

多线程一直是工作或面试过程中的高频知识点,今天给大家分享一下使用 ThreadPoolTaskExecutor 来自定义线程池和实现异步调用多线程。 一、ThreadPoolTaskExecutor 本文采用 Executors 的工厂...

CREATE_17
今天
5
0
CSS盒子模型

CSS盒子模型 组成: content --> padding --> border --> margin 像现实生活中的快递: 物品 --> 填充物 --> 包装盒 --> 盒子与盒子之间的间距 content :width、height组成的 内容区域 padd......

studywin
今天
7
0
修复Win10下开始菜单、设置等系统软件无法打开的问题

因为各种各样的原因导致系统文件丢失、损坏、被修改,而造成win10的开始菜单、设置等系统软件无法打开的情况,可以尝试如下方法解决 此方法只在部分情况下有效,但值得一试 用Windows键+R打开...

locbytes
昨天
8
0
jquery 添加和删除节点

本文转载于:专业的前端网站➺jquery 添加和删除节点 // 增加一个三和一节点function addPanel() { // var newPanel = $('.my-panel').clone(true) var newPanel = $(".triple-panel-con......

前端老手
昨天
8
0
一、Django基础

一、web框架分类和wsgiref模块使用介绍 web框架的本质 socket服务端 与 浏览器的通信 socket服务端功能划分: 负责与浏览器收发消息(socket通信) --> wsgiref/uWsgi/gunicorn... 根据用户访问...

ZeroBit
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部