声明:本文内容是从网络书籍整理而来,并非原创。

用户管理的例子

  1. 先看一张用户管理的类图: 
  2. 再看一眼上面的图,思考:这样合理吗?

  3. 这个接口是一个很糟糕的设计! 用户的属性和行为竟然混合在一起!!!

  4. 正确的做法是把用户的信息抽取成一个业务对象(Bussiness Object,简称 BO),把行为抽取成另外一个接口中,我们把这个类图重新画一下: 

  5. 这样划分成了两个接口,IUserBO 负责用户的属性,IUserBiz 负责用户的行为,因为是面向的接口编程,所有当产生了这个 UserInfo 对象之后,既可以把它当 IUserBO 接口使用,也可以当 IUserBiz 接口使用,类似下面代码:

    IUserBiz userInfo = new UserInfo(); 
    
    //我要赋值了,我就认为它是一个纯粹的BO
    IUserBO userBO = (IUserBO)userInfo;
    userBO.setPassword("abc"); //我要执行动作了,我就认为是一个业务逻辑类
    IUserBiz userBiz = (IUserBiz)userInfo;
    userBiz.deleteUser();
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  6. 问题解决了,但实际中我们更倾向于使用两个不同的类或接口, 一个就是IUserBO,一个是IUserBiz,如下图: 

  7. 以上我们把一个接口拆分成两个接口的动作,就是依赖了单一职责原则,那什么是单一职责原则呢?

    单一职责原则:应该有且仅有一个原因引起类的变更 
    SRP 的原话解释是:There should never be more than one reason for a class to change。

打电话的例子

  1. 电话通话的时候有四过程发生:拨号、通话、回应、挂机,那么看下接口图: 
     
    接口代码:

    public interface IPhone { 
    
      //拨通电话
    public void dial(String phoneNumber); //通话
    public void chat(Object o); //回应,只有自己说话而没有回应,那算啥?!
    public void answer(Object o); //通话完毕,挂电话
    public void huangup();
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  2. 想想,符合单一职责原则吗?

  3. 其实它有两个职责:一个是协议管理,一个是数据传送,diag()和 huangup()两个方法实现的是协议管理,拨号接通和关闭;chat()和answer()是数据的传送,把我们说的话转换成模拟信号或者是数字信号传递到对方,然后再把对方传递过来的信号还原成我们听的懂人话。这两个职责互不影响,所以考虑拆开,如下图: 

  4. 这种设计完全满足类和接口的单一职责要求,但是一个手机类要把 ConnectionManager 和DataTransfer 组合在一块才能使用,组合是一种强耦合关系,都是有共同的生命期,这样的强耦合关系还不如使用接口实现的方式呢,而且还增加了类的复杂性,多了两个类呀,好,我们修改一下类图: 

  5. 这样设计才为完美,一个手机实现了两个接口,把两个职责融合一个类中,你会觉得这个 Phone有两个原因引起变化了呀,是的是的,但是别忘记了我们是面向接口编程,我们对外公布的是接口而不是实现类;而且如果真要实现类的单一职责的话,这个就必须使用了上面组合的方式了,那这个会引起类间耦合过重的问题。

    所以,对于接口,我们在设计的时候一定要做到单一,但是对于实现类就需要多方面考虑了,生搬硬套单一职责原则会引起类的剧增,给维护带来非常多的麻烦;而且过分的细分类的职责也会人为的制造系统的复杂性,本来一个类可以实现的行为非要拆成两个,然后使用聚合或组合的方式再耦合在一起,这个是人为制造了系统的复杂性,所以原则是死的,人是活的,这句话是非常好的。

单一职责的好处:

  1. 类的复杂性降低,实现什么职责都有清晰明确的定义;
  2. 可读性提高,复杂性降低,那当然可读性提高了;
  3. 可维护性提高,那当然了,可读性提高,那当然更容易维护了;
  4. 变更引起的风险降低,变更是必不可少的,接口的单一职责做的好的话,一个接口修改只对相应的实现类有影响,与其他的接口无影响,这个是对项目有非常大的帮助。

    单一职责原则最难划分的就是职责,一个职责一个接口,但是问题是“职责”是一个没有量化的标准,一个类到底要负责那些职责?这些职责怎么细化?细化后是否都要有一个接口或类?这个都是需要从实际的项目区考虑的,从功能上来说,定义一个 IPhone 接口也没有错,实现了电话的功能呀,而且设计还很简单,就一个接口一个实现类,真正的项目我想大家一般都是会这么设计的,从设计原则上来看就有问题了,有两个可以变化的原因放到了一个接口中了,这就为以后的变化带来了风险,我从 2G 通讯协议修改到 3G 通讯,你看看你提供出的接口 IPhone 是不是要修改了?接口修改对其他的 Invoker 是不是有很大影响?!

方法的单一职责原则

单一职责使用于接口、类,同时也使用方法,什么意思呢?一个方法尽可能做一件事情,比如一个方法修改用户密码,别把这个方法放到“修改用户信息”方法中,这个方法的颗粒度很粗,比如这样一个方法: 

在 IUserManager 中定义了一个方法叫 changeUser,根据传递的 type 不同,把可变长度参数changeOptions 修改到 userBo 这个对象上,并调用持久层的方法保存到数据库中。在我的项目组中如果有人写了这样一个方法,我不管他写了多上程序化了多少工夫,一律重写!原因是:方法职责不清晰,不单一,一般方法设计成这样的: 
 
你要修改用户名称,就调用 changeUserName 方法,你要修改家庭地址就调用 changeHomeAddress,你要修改单位单户就调用 changeOfficeTel 方法,每个方法的职责就非常清晰,这也是一个良好的设计习惯。 
所以,不管是对接口、类、方法使用了单一规则原则,那么快乐的就不仅仅是你了,还有你项目的成员,你的板,减少了因为变更引起的工作量呀,加官进爵等着你幺!

疑惑

你看到这里,就会问我,你写是类的设计原则吗?你通篇都在说接口的单一职责,类的单一职责你都违背了呀,呵呵,这个还真是的,我的本意是想把这个原则讲清楚,类的单一职责嘛,这个很简单,但当我回头写的时候,发觉才不是这么回事,翻看了以前一些设计和代码,基本上拿的出手的类设计都是和单一职责向违背的,静下心来回忆,发觉每一个类这样设计都是有原因的。这几天我查阅了 wikipedia、oodesign 等几个网站,专家和我也有类似的经验,基本上类的单一职责都用了类似的一句话来说“This is sometimes hard to see” ,这句话翻译过来就是“这个有时候很难说” ,是的,类的单一职责确实受非常多的因素制约,纯理论的来讲,这个原则是非常优秀的,但是现实有现实难处,你必须去考虑项目工期、成本、人员技术水平、硬件情况、网络情况甚至有时候还要考虑政府政策、垄断协议等等原因。

所以,对于单一职责原则,我的建议是接口一定要做到单一职责,类设计尽量只有一个原因引起变化。

版权声明:本文为博主原创文章,未经博主允许不得转载。

 

六大设计原则——单一职责原则【Single Responsibility Principle】的更多相关文章

  1. 面向对象设计原则 单一职责原则(Single responsibility principle)

    单一职责原则(SRP:Single responsibility principle) 又称单一功能原则,面向对象的基本原则之一.它规定 一个类应该只有一个发生变化的原因. 该原则由罗伯特·C·马丁( ...

  2. 设计模式值六大原则——设计模式之六大原则——单一职责原则(SRP)

    定义: 应该有且仅有一个原因引起类的变更. There should never be more than one reason for a class to change. 优点: 1.类的复杂性降 ...

  3. Java设计原则—单一职责原则(转)

    定义: 应该有且仅有一个原因引起类的变更. There should never be more than one reason for a class to change. 优点: 1.类的复杂性降 ...

  4. 单一职责原则(Single Responsibility Principle)

    单一职责原则(SRP:The Single Responsibility Principle) 一个类应该有且只有一个变化的原因. There should never be more than on ...

  5. 北风设计模式课程---单一职责原则(Single Responsibility Principle)

    北风设计模式课程---单一职责原则(Single Responsibility Principle) 一.总结 一句话总结: 一个类应该有且只有一个变化的原因:单一职责原则(SRP:Single Re ...

  6. 设计模式之单一职责原则(SRP)

    自己之前写过一些关于设计模式的博客,但是大部分都写得比较匆忙.现在正好趁年前有时间,笔者打算好好地整理一下自己这块知识结构.开篇的第一个原则就是设计原则里面最简单的一个原则--单一职责原则. 想必大家 ...

  7. 080 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 05 单一职责原则

    080 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 05 单一职责原则 本文知识点:单一职责原则 说明:因为时间紧张,本人写博客过程中只是 ...

  8. IOS设计模式的六大设计原则之单一职责原则(SRP,Single Responsibility Principle)

    定义 就一个类而言,应该仅有一个引起它变化的原因. 定义解读 这是六大原则中最简单的一种,通俗点说,就是不存在多个原因使得一个类发生变化,也就是一个类只负责一种职责的工作. 优点 类的复杂度降低,一个 ...

  9. 【设计原则和编程技巧】单一职责原则 (Single Responsibility Principle, SRP)

    单一职责原则 (Single Responsibility Principle, SRP) 单一职责原则在设计模式中常被定义为“一个类应该只有一个发生变化的原因”,若我们有两个动机去改写一个方法,那这 ...

随机推荐

  1. jQuery $.fn.extend方式自定义插件

    之前例子是扩展jQuery的工具方法,即通过$.xxx(para);的形式来使用的.下面是扩展jquery对象的方法,即任意一个jquery对象都已访问. 具体如下: wyl.js: (functio ...

  2. 修改SQL Server 排序规则 (未能排它地锁定数据库以执行该操作)

    use master go alter database DBName set single_user go alter database DBName COLLATE Chinese_PRC_CI_ ...

  3. Python3 官方文档翻译 - 4.7 函数定义

    4.7.1 默认函数定义 最常用的就是为一个或多个参数设定默认值,这让函数可以用比定义时更少的参数来调用,例如: def ask_ok(prompt, retries=4, complaint='Ye ...

  4. Buy Tickets(线段树)

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 16607   Accepted: 8275 Desc ...

  5. Python重写C语言程序100例--Part9

    ''' [程序71] 题目:编写input()和output()函数输入,输出5个学生的数据记录. 1.程序分析: 2.程序源码: 使用list来模拟结构(不使用class) stu = [strin ...

  6. UIApplication相关

    1,显示应用图标右上角的红色提示 application.applicationIconBadgeNumber = 10; 2.修改状态栏的类型 在当前控制器下设置 - (UIStatusBarSty ...

  7. Linux DM9000网卡驱动程序完全分析

    Linux DM9000网卡驱动程序完全分析http://blog.csdn.net/ypoflyer/article/details/6209922

  8. BZOJ 4034: [HAOI2015]T2( 树链剖分 )

    树链剖分...子树的树链剖分序必定是一段区间 , 先记录一下就好了 ------------------------------------------------------------------ ...

  9. centos6.5 mysql安装+远程访问+备份恢复+基本操作+卸载

    参考博文: Linux学习之CentOS(十三)--CentOS6.4下Mysql数据库的安装与配置 MySQL修改root密码的多种方法 MySQL的备份与还原 解决mysql导入还原时乱码的问题 ...

  10. Swift 版本历史记录(关注)

    http://numbbbbb.gitbooks.io/-the-swift-programming-language-/content/chapter1/03_revision_history.ht ...