1.定义:

  不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。 

2.使用场景:

  如果类A有两个职责:d1,d2。当职责d1需要修改时,可能会导致原本运行正常的职责d2功能产生问题。即如果一个类包含多种职责,就应该把类拆分。分别建立两个类A、B,让A负责d1,B负责d2。当需要修改某一职责,那么将不会对另外一个功能产生影响。

3.使用特点

  一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。
    单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关实践经验。

4.实现案例

(1)用一个类秒数动物呼吸这个场景
class Animal {
public void breathe(string animal){
Console.WriteLine(animal+"呼吸空气");
}
}
class Program{
static void Main(string[] args){
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("羊");
animal.breathe("猪");
animal.breathe("鱼");
Console.ReadLine();
}
}
 
(2)我们发现不是所有动物都是呼吸空气的,比如鱼就是呼吸水的,根据单一职责原则,我们将Animal类细分为陆生动物类和水生动物类,如下所示:
class Terrestrial {
public void breathe(string animal){
Console.WriteLine(animal+"呼吸空气");
}
}
class Aquatic{
public void breathe(string animal){
Console.WriteLine(animal + "呼吸水");
}
}
class Program {
static void Main(string[] args){
Terrestrial terrestrial = new Terrestrial();
terrestrial.breathe("牛");
terrestrial.breathe("羊");
terrestrial.breathe("猪");
Aquatic aquatic = new Aquatic();
aquatic.breathe("鱼");
Console.ReadLine();
}
}
(3)我们发现这样修改的花销很大,既要将原来的类分解,又要修改客户端。而直接修改Animal类虽然违背了单一职责原则,但花销小的多,如下所示:
class Animal{
public void breathe(string animal){
if ("鱼".Equals(animal)){
Console.WriteLine(animal + "呼吸水");
} else {
Console.WriteLine(animal + "呼吸空气");
}
}
}
class Program{
static void Main(string[] args){
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("羊");
animal.breathe("猪");
animal.breathe("鱼");
Console.ReadLine();
}
}
(4)可以看到,这种修改方式简单的多。但却存在隐患,一天需要将鱼分为淡水鱼,海水鱼,又需要修改Animal类的breathe方法。可能给“猪牛羊”等相关功能带来风险,这种修改直接在代码级别违背了单一职责原则,虽然修改起来最简单,但隐患最大。还有一种修改方式:
class Animal{
public void breathe(string animal){
Console.WriteLine(animal + "呼吸空气");
}
public void breathe2(string animal){
Console.WriteLine(animal + "呼吸水");
}
}
class Program{
static void Main(string[] args){
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("羊");
animal.breathe("猪");
animal.breathe2("鱼");
Console.ReadLine();
}
}
这种修改方式没有改动原来的方法,而是在类中新加了一个方法,这样虽然违背了单一职责原则,但在方法级别上却是符合单一职责原则的。那么在实际编程中,采用哪一种呢?我的原则是,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方法数量足够少,才可以在方法级别违反单一职责原则。

5.优缺点:

(1)单一职责优点

[1]类的复杂性降低,实现什么职责都有清晰明确的定义;
[2]可读性提高,复杂性减低,可读性当然提高;
[3]可维护性提高,可读性提高,可维护性当然提高;
[4]变更引起的风险减低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的类有影响,对其他接口无影响,这对系统的扩展性、维护性都有非常大的帮助。

6.注意事项

  单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但是“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。
  接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。
 

设计模式原则(1)--Single Responsibility Principle(SRP)--单一职责原则的更多相关文章

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

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

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

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

  3. 面象对象设计原则之一:单一职责原则(Single Responsibility Principle, SRP)

    单一职责原则是最简单的面向对象设计原则,它用于控制类的粒度大小.单一职责原则定义如下:单一职责原则(Single Responsibility Principle, SRP):一个类只负责一个功能领域 ...

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

    using System; using System.Collections.Generic; using System.Text; namespace SingleResponsibilityPri ...

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

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

  6. 第2章 面向对象的设计原则(SOLID):1_单一职责原则(SRP)

    1. 单一职责原则(Single Responsibility Principle,SRP) 1.1 单一职责的定义 (1)定义:一个类应该仅有一个引起它变化的原因.这里变化的原因就是所说的“职责”. ...

  7. C#设计模式系列:单一职责原则(Single Responsibility Principle)

    1.单一职责原则的核心思想 一个类应该有且只有一个变化的原因. 2.为什么要引入单一职责原则 单一职责原则将不同的职责分离到单独的类,每一个职责都是一个变化的中心.当需求变化时,这个变化将通过更改职责 ...

  8. 【设计模式六大原则1】单一职责原则(Single Responsibility Principle)

        http://blog.csdn.net/zhengzhb/article/category/926691/1 图片素材来源,java学习手册 ps.内容为自己整理   定义:不要存在多于一个 ...

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

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

随机推荐

  1. [JavaScript] js实现保存文件到本地

    function fake_click(obj) { var ev = document.createEvent("MouseEvents"); ev.initMouseEvent ...

  2. 十分钟内在Ubuntu系统上搭建Mono开发环境(Mono软件Ubuntu系统国内镜像源、Mono国内镜像源)

    Mono软件Ubuntu系统国内镜像源.Mono国内镜像源 http://download.githall.cn/repo 替换为国内源(非官方)有利于加快mono的安装速度,一般情况下,完成mono ...

  3. spring@Transactional注解事务不回滚不起作用无效的问题处理

    这几天在项目里面发现我使用@Transactional注解事务之后,抛了异常居然不回滚.后来终于找到了原因. 如果你也出现了这种情况,可以从下面开始排查. 一.特性先来了解一下@Transaction ...

  4. Is it possible to display icons in a PopupMenu?

    I really like the new PopupMenu we got in 3.0, but I just can't display any icons next to the menu i ...

  5. JAVA中 XML与数据库互转 学习笔记三

    要求 必备知识 JAVA基础知识,XML基础知识,数据库的基本操作. 开发环境 MyEclipse10/MySql5.5 资料下载 源码下载   数据库在数据查询,修改,保存,安全等方面与其他数据处理 ...

  6. poj1330-----------关于公共祖先的问题

    关于公共祖先的问题分类: 这类问题有多种解法和类型,根据题目给出的信息去判断使用哪一种 1.给你树,只支持从父亲找儿子,不支持儿子找父亲,最后要求最近公共祖先,使用dfs或者分治 2.支持儿子找父亲, ...

  7. CentOS下SSH远程免密登录服务器

    .5服务器上配置,通过ssh远程免密登录192. 1.安装SSH,此处省略 2.生成公钥和私钥,生成的秘钥默认在/root/.ssh/文件夹里面 [root@localhost ~ ::&&a ...

  8. linux-centos使用 wget命令获取jdk

    1, 首先去官网看下地址是否变化了 2, 然后输入以下命令即可 wget --no-check-certificate --no-cookies --header "Cookie: orac ...

  9. @Async的使用

    从Spring3.x 开始,加入@Async这个注解,用户异步线程处理,使用起来很方便. 使用配置如下:spring-task.xml <task:executor id="execu ...

  10. linux-openvpn

    1.安装openvpn 1)安装需要的依赖,需要用到epel源 #yum -y install  epel-release 修改epel.repo文件enabled=1 #yum install ea ...