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. Spring Boot中使用Flyway来管理数据库版本

    flyway是一个开源的数据库迁移工具.类似于数据库的版本控制工具.flyway的数据库修改文件默认放在resource下的db.migration文件夹中,以V{version_number}__{ ...

  2. Swift5 语言参考(六) 声明

    一个声明引入了一个新的名称或构建到你的程序.例如,您使用声明来引入函数和方法,引入变量和常量,以及定义枚举,结构,类和协议类型.您还可以使用声明来扩展现有命名类型的行为,并将符号导入到其他地方声明的程 ...

  3. Node.js对MongoDB进行增删改查操作

    MongoDB简介 MongoDB是一个开源的.文档型的NoSQL数据库程序.MongoDB将数据存储在类似JSON的文档中,操作起来更灵活方便.NoSQL数据库中的文档(documents)对应于S ...

  4. 生成代码的代码 之 POJO生成器

    我们在写Java代码时候,有时候需要写一些POJO类,也就是只有一些属性和get, set方法的类.例如,在写REST 服务时候,利用Jersery + Jackson,可以把输入的JSON字符串自动 ...

  5. TCP 流量控制、拥塞控制

    流量控制: 流量控制是为了控制发送方发送速率,保证接收方来得接收. 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率.将窗口字段设置为 0,则发送方不能发送数据. ...

  6. 改善android性能工具篇【zipalign】

    什么是Zipalign?      Zipalign是一个android平台上整理APK文件的工具,它首次被引入是在Android 1.6版本的SDK软件开发工具包中.它能够对打包的Android应用 ...

  7. CVPR2019 | Mask Scoring R-CNN 论文解读

    Mask Scoring R-CNN CVPR2019 | Mask Scoring R-CNN 论文解读 作者 | 文永亮 研究方向 | 目标检测.GAN 推荐理由: 本文解读的是一篇发表于CVPR ...

  8. 【胡思乱想】命令模式 与 Thread Runnable

    实现线程任务有两种方式,一种是创建Runnable/Callable对象,传递给Thread.另一种是子类重写Thread的run方法. 我觉得前一种像极了命令模式,或者说应该是命令模式的一个使用案例 ...

  9. mysql dbcp Caused By: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy ...

  10. 【K8S学习笔记】Part1:使用端口转发访问集群内的应用

    本文介绍如何使用kubectl port-forward命令连接K8S集群中运行的Redis服务.这种连接方式有助于数据库的调试工作. 注意:本文针对K8S的版本号为v1.9,其他版本可能会有少许不同 ...