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. UI的设计,适配器,以及RecyclerView无法加载的解决办法

    这本书里讲到的界面设计都是用最基本的方式实现的,即编写xml文件 所有的控件都具有宽度和高度属性,即android:layout_width和android:layout_height,这两个属性对应 ...

  2. POJ 2707

    #include<iostream> #include<stdio.h> #include<algorithm> using namespace std; int ...

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

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

  4. java中result和resultSet

    ResultSet: 1,定义         public interface ResultSet 表示数据库结果集的数据表,通常通过执行查询数据库的语句生成. 2,获得         State ...

  5. 常用处理数据用法es6 语法糖总结

    一 循环(数组 ,集合)   1 forEach-----------可以遍历得到vaue和index   const arr = ['red', 'green', 'blue'];arr.forEa ...

  6. 在matlab中实现梯度下降法

    梯度下降法的原理,本文不再描述,请参阅其它资料. 梯度下降法函数function [k ender]=steepest(f,x,e),需要三个参数f.x和e,其中f为目标函数,x为初始点,e为终止误差 ...

  7. Python:线程指南

    1. 线程基础 1.1. 线程状态 线程有5种状态,状态转换的过程如下图所示: 1.2. 线程同步(锁) 多线程的优势在于可以同时运行多个任务(至少感觉起来是这样).但是当线程需要共享数据时,可能存在 ...

  8. c++的动态绑定和静态绑定

    为了支持c++的多态性,才用了动态绑定和静态绑定. 1.对象的静态类型:对象在声明时采用的类型.是在编译期确定的. 2.对象的动态类型:目前所指对象的声明.在运行期决定.对象的动态类型可以更改,但是静 ...

  9. Android_触摸事件传递机制

    Android中dispatchTouchEvent,onInterceptTouchEvent, onTouchEvent的理解ecandroid中的事件类型分为按键事件和屏幕触摸事件,Touch事 ...

  10. springboot 多模块 -- 将 dao(mybatis) 拆分出去

    前言: 以前我们在建项目的时候, 要么将所有的package建在一个项目里面, 在处理引用的时候, 真的很方便. 不用担心, 有些东西配置不到或者读取不到. 或者, 将package独立出去, 到一个 ...