1. 背景

    类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。

2. 定义

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

3. 宏观上

   类层次上存在单一职责原则,同样方法层次上也存在单一职责原则。

4. 补充两个概念

高内聚:内聚是指类内部的属性和行为,高内聚就是指:一个类的属性和行为与这个类非常密切,称为高内聚。
   低耦合:耦合是指类与类之间或者模块与模块之间的联系,低耦合就是指:耦合度低,易重用、使用灵活。

5. 案例

 需求一:有牛和羊两种动物,它们都需要呼吸空气。

解决思路:构造动物类,封装呼气空气的方法。

  public class Animal
{
public string myName { get; set; } private string _name = null;
public Animal()
{ }
public Animal(string name)
{
this._name = name;
} //封装呼吸空气的方法
public void BreathAir()
{
Console.WriteLine(this._name + "呼吸空气");
}
}

 需求变更:又多了鱼这个物种,它们需要呼吸空气。

解决方案一:直接在BreathAir上加判断,但是这样违背了方法意义上的单一职责原则

    public void BreathAir()
{
if (this._name.Equals("鱼"))
{
Console.WriteLine(this._name + "呼吸水"); //违背了方法级别的单一职责
}
else
{
Console.WriteLine(this._name + "呼吸空气");
}
}

  解决方案二:在Animal类中添加一个BreathWater的方法,但是这样违背了类意义上的单一职责原则

        //封装呼吸水的方法
public void BreathWater()
{
Console.WriteLine(this._name + "呼吸水");
}

解决方案三:新建一个WaterAnimal类,在里面封装BreathWater的方法,无论是类级别还是方法级别,都满足了单一职责原则,但是改动成本太大,耗时太长。

   public class WaterAnimal
{
private string _name = null;
public WaterAnimal(string name)
{
this._name = name;
}
//封装呼吸水的方法
public void BreathWater()
{
Console.WriteLine(this._name + "呼吸水");
}
}

 综合调用:

        public static void show()
{
//下面模拟单一职责面对需求变更的情况。
//需求1:有牛和羊两种动物,它们需要呼吸空气
//解决思路:构造动物类→封装呼吸空气的方法
Animal animal1 = new Animal("牛");
Animal animal2 = new Animal("羊");
animal1.BreathAir();
animal2.BreathAir(); //需求2:又多了鱼这个物种,它们需要呼吸水
//解决方案一:在Breath里加判断,但是违背了方法级别的单一职责原则
Animal animal3 = new Animal("鱼");
animal3.BreathAir(); //解决方案二:在Animal类中添加一个BreathWater的方法,但是违背了类级别的单一职责原则
Animal animal4 = new Animal("鱼");
animal4.BreathWater(); //解决方案三:新建一个WaterAnimal类,在里面封装BreathWater的方法,无论是类级别还是方法级别,都满足了单一职责原则,但是改动成本太大,耗时太长
WaterAnimal animal5 = new WaterAnimal("鱼");
animal5.BreathWater(); }

  解决方案四:利用委托来解决。

         /// <summary>
/// 利用委托的插件式编程
/// </summary>
public static void show2()
{
Console.WriteLine("------------------下面是利用委托来解决--------------------");
Animal animal1 = new Animal() { myName = "牛" };
Animal animal2 = new Animal() { myName = "羊" };
Animal animal3 = new Animal() { myName = "鱼" };
Action<Animal> act1 = Utils.BreathWater;
Action<Animal> act2 = Utils.BreathAir;
act1.Invoke(animal1);
act1.Invoke(animal2);
act2.Invoke(animal3);
}

6. 单一职责原则的好处

 (1). 降低类复杂性,一个类只负责一项职责要比负责多项职责简单的多。

(2). 提高类的可读性,便于维护。

(3). 变更引起的风险低,修改一个类的功能,显著降低对其他类的影响。

7. 我的总结

如果完全遵循单一职责原则,当业务复杂的时候,改动成本是最大的。所以我的原则是:根据实际业务场景,来决定是否违背方法或类层次上的单一职责原则。

01-单一职责原则(SPR)的更多相关文章

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

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

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

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

  3. C#软件设计——小话设计模式原则之:单一职责原则SRP

    前言:上篇C#软件设计——小话设计模式原则之:依赖倒置原则DIP简单介绍了下依赖倒置的由来以及使用,中间插了两篇WebApi的文章,这篇还是回归正题,继续来写写设计模式另一个重要的原则:单一职责原则. ...

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

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

  5. SRC单一职责原则

    一.定义 一个类应该只有一个发生变化的原因. 二.为什么要使用SRC 因为每一个职责都是变化的一个轴线.当需求变化时,这种变化就会反映为类的职责的变化.如果一个类承担了多于一个的职责,那么引起它变化的 ...

  6. 开放-封闭原则(OCP)开-闭原则 和 依赖倒转原则,单一职责原则

    单一职责原则 1.单一职责原则(SRP),就一个类而言,应该仅有一个引起它变化的原因 2.如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会消弱或抑制这个类完成其他职责的能力. ...

  7. 敏捷软件开发:原则、模式与实践——第8章 SRP:单一职责原则

    第8章 SRP:单一职责原则 一个类应该只有一个发生变化的原因. 8.1 定义职责 在SRP中我们把职责定义为变化的原因.如果你想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责.同时,我 ...

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

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

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

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

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

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

随机推荐

  1. Mysql 5.7.21 单机多实例安装

    下载MySQL 5.7 二制包 [root@MySQL ~]# wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.21-linu ...

  2. Jmeter While Controller 使用${__jexl2(,)}

    1. String [] str ={"1","2","3"}; vars.putObject("strArray",s ...

  3. [日常工作]vCenter下虚拟机设置与宿主机时间同步的方法

    1. ESXi 能够实现CPU超售 同事开启多与CPU个数的虚拟机 不通的虚拟机采用了时间分片的处理, 所以有时候虚拟机内的时间可能会比宿主机的时间过的更慢, 越来越久之后虚拟机的时间就会比较离谱了. ...

  4. [日常工作] Inspur 服务器安装ESXi的简单过程

    1. 公司里面使用虚拟化来进行功能测试 性能测试, 现阶段和之前主要是用虚拟机来搞. 前期用过hyperV 但是感觉 没有SystemCenter的VMM的授权比较难搞一些. 所以还是用ESXi的多了 ...

  5. Java之静态代码块

    有一些情况下,有些代码需要在项目启动的时候就执行,则需要使用静态代码块,这种代码是主动执行的.Java中的静态代码块是在虚拟机加载类的时候,就执行的,而且只执行一次.如果static代码块有多个,JV ...

  6. BZOJ2157旅游——树链剖分+线段树

    题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路 ...

  7. java 使用 WebUploader

    参考: http://blog.csdn.net/finalAmativeness/article/details/54668090 最近项目需要多文件上传. 所以使用了 baidu的 webuplo ...

  8. Linux磁盘和文件系统简介

    Linux磁盘和文件系统简介 1.文件系统:存储设备上存储数据的方式方法 磁盘主要由盘片.机械手臂.磁头和主轴马达组成,而数据的写入实际是写在盘片上,磁盘的最小存储单位为扇区,每个扇区为512字节,扇 ...

  9. CF1101D GCD Counting(数学,树的直径)

    几个月的坑终于补了…… 题目链接:CF原网  洛谷 题目大意:一棵 $n$ 个点的树,每个点有点权 $a_i$.一条路径的长度定义为该路径经过的点数.一条路径的权值定义为该路径经过所有点的点权的 GC ...

  10. Spring详细教程

    Spring学习总结---- 一.导入Spring必须的jar包 二.简单示例入门注入一个User 1.编写User实体类 package test.Spring.helloworld; import ...