C#实现六大设计原则之单一职责原则

单一职责(SRP)定义:

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

问题由来:

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

解决方案:

遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;同理,当修改T2时,也不会使职责P1发生故障风险。

ps:

说到单一职责原则,很多人都会不屑一顾。因为它太简单了。稍有经验的程序员即使从来没有读过设计模式、从来没有听说过单一职责原则,在设计软件时也会自觉的遵守这一重要原则,因为这是常识。在软件编程中,谁也不希望因为修改了一个功能导致其他的功能发生故障。而避免出现这一问题的方法便是遵循单一职责原则。虽然单一职责原则如此简单,并且被认为是常识,但是即便是经验丰富的程序员写出的程序,也会有违背这一原则的代码存在。为什么会出现这种现象呢?因为有职责扩散。所谓职责扩散,就是因为某种原因,职责P被分化为粒度更细的职责P1和P2。

比如:类T只负责一个职责P,这样设计是符合单一职责原则的。后来由于某种原因,也许是需求变更了,也许是程序的设计者境界提高了,需要将职责P细分为粒度更细的职责P1,P2,这时如果要使程序遵循单一职责原则,需要将类T也分解为两个类T1和T2,分别负责P1、P2两个职责。但是在程序已经写好的情况下,这样做简直太费时间了。所以,简单的修改类T,用它来负责两个职责是一个比较不错的选择,虽然这样做有悖于单一职责原则。(这样做的风险在于职责扩散的不确定性,因为我们不会想到这个职责P,在未来可能会扩散为P1,P2,P3,P4……Pn。所以记住,在职责扩散到我们无法控制的程度之前,立刻对代码进行重构。)

C#代码举例说明:

我们用一个天空类, 去描述一个动物飞的动作。

class Program
    {
        static void Main(string[] args)
        {
            Sky SkyExample = new Sky();
            SkyExample.fly("老鹰");
            SkyExample.fly("麻雀");

            Console.ReadKey();
        }
    }

    public class Sky
    {
        public void fly(string name)
        {
            Console.WriteLine(name + "天上飞");
        }
    }

但是仔细看, 会发现问题, 并不是所有的动物都会在天上飞, 比如狗, 它就是在地上跑。

所以要去修改它, 但如果要在遵循单一职责的原则下, 我们则需要新增一个地的类(Land), 提供一部分跑的动作 (run),

class Program
    {
        static void Main(string[] args)
        {
            Sky SkyExample = new Sky();
            SkyExample.fly("飞机");
            SkyExample.fly("老鹰");
            SkyExample.fly("麻雀");

            Land LandExample = new Land();
            LandExample.run("猪");
            LandExample.run("狗");
            LandExample.run("马");

            Console.ReadKey();
        }
    }

    public class Sky
    {
        public void fly(string name)
        {
            Console.WriteLine(name + "天上飞");
        }
    }

    public class Land
    {
        public void run(string name)
        {
            Console.WriteLine(name + "地上跑");
        }
    }

可以看到,这种修改方式没有改动原来的类,而是新增了一个类加了一个方法, 这个即在类级别符合单一职责原则, 也在方法上符合单一职责, 因为它没有动或影响原来的代码, 但是在实际的

开发过程中, 我们往往会将类变得更抽象(sky则改成不再是天空,变成Animal), 而我们则需要在 Animal 类下, 提供多个方法, 可以 fly,run,climb等等, 这样也就不会我们重新建一个类去到达目的。

显然, 这种方法违背了单一职责原则, 但是这样在方法级别上是符合单一职责原则得。

遵循单一职责原的优点:

·    可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;

·    提高类的可读性,提高系统的可维护性;

·    变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。

ps: 需要说明的一点是单一职责原则不只是面向对象编程思想所特有的,只要是模块化的程序设计,都适用单一职责原则。

到此这篇关于C#实现六大设计原则之单一职责原则的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 浅谈C#六大设计原则

    笔者作为一个菜鸟,会尝试以简单的代码和容易理解的语句去解释这几种原则的特性和应用场景. 这六种原则分别为单一职责原则.接口隔离原则.里氏替换原则.迪米特法则.依赖倒置原则.开闭原则. 单一职责原则 单一职责原则(SRP:Single responsibility principle),规定一个类中应该只有一个原因引起类的变化. 单一职责原则的核心就是解耦和增强内聚性. 问题: // 假设此类是数据库上下文 public class DatabaseContext { } public class

  • C#实现六大设计原则之里氏替换原则

    定义: 1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子型. 2:所有引用基类的地方必须能透明地使用其子类的对象. 问题由来: 有一功能P1,由类A完成.现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成. 新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障. 解决

  • C#实现六大设计原则之依赖倒置原则

    依赖倒置原则(DIP)定义: 高层模块不应该依赖低层模块,二者都应该依赖其抽象:抽象不应该依赖细节:细节应该依赖抽象. 问题由来: 类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块, 负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案: 将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率. ps: 依赖倒置原则

  • C#实现六大设计原则之迪米特法则

    定义: 一个对象应该对其他对象保持最少的了解. 问题由来: 类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大. 解决方案: 尽量降低类与类之间的耦合. PS: 自从我们接触编程开始,就知道了软件编程的总的原则:低耦合,高内聚. 无论是面向过程编程还是面向对象编程,只有使各个模块之间的耦合尽量的低,才能提高代码的复用率. 低耦合的优点不言而喻,但是怎么样编程才能做到低耦合呢?那正是迪米特法则要去完成的. 迪米特法则又叫最少知道原则,最早是在1987年由美国Northe

  • C#实现六大设计原则之接口隔离原则

    接口隔离原则(ISP)定义: 客户端不应该依赖它不需要的接口:一个类对另一个类的依赖应该建立在最小的接口上. 问题由来: 类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法. 解决方案: 将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系.也就是采用接口隔离原则. 举例来说明接口隔离原则: 类A依赖接口I中的方法1.方法2.方法3,类B是对类A依赖的实现. 类C依赖接口I中的方法1.方法4.

  • 六大设计原则之开闭原则

    定义: 一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 问题由来: 在软件的生命周期内,因为变化.升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试. 解决方案: 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化. 开闭原则是面向对象设计中最基础的设计原则,它指导我们如何建立稳定灵活的系统. 开闭原则可能是设计模式六项原则中定义最模糊的一个了,它只告诉我们

  • C#实现六大设计原则之单一职责原则

    单一职责(SRP)定义: 不要存在多于一个导致类变更的原因,通俗的说,即一个类只负责一项职责. 问题由来: 类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障. 解决方案: 遵循单一职责原则.分别建立两个类T1.T2,使T1完成职责P1功能,T2完成职责P2功能.这样,当修改类T1时,不会使职责P2发生故障风险:同理,当修改T2时,也不会使职责P1发生故障风险. ps: 说到单一职责原则,很多人都会不屑一顾.因为

  • PHP面向对象五大原则之单一职责原则(SRP)详解

    本文实例讲述了PHP面向对象五大原则之单一职责原则(SRP).分享给大家供大家参考,具体如下: 单一职责原则(Single Pesponsibility Principle, SRP) 单一职责有两个含义: 一个是避免相同的职责分散到不同的类中, 别一个是避免一个类承担太多职责 为什么要遵守SRP呢? (1)可以减少类之间的耦合 如果减少类之间的耦合,当需求变化时,只修改一个类,从而也就隔离了变化:如果一个类有多个不同职责,它们耦合在一起,当一个职责发生变化时,可能会影响到其他职责. (2)提高

  • Java设计模式七大原则之单一职责原则详解

    目录 定义 案例 需求 方案一 方案二 对比分析 总结 如何遵守单一职责原则 定义 单一职责原则(Single Responsibility Principle, SRP),有且仅有一个原因引起类的变更.简单来说,就是针对一个java类,它应该只负责一项职责.例如一个Test.java类,它有两个职责:职责1,职责2.当职责1进行修改时,有可能影响到职责2,所以需要将Test.java类拆分成Test1.java和Test2.java两个单一职责的类. 案例 需求 有一个交通工具类,里面定义一个

  • C#面向对象设计原则之单一职责原则

    单一职责原则(SRP) 定义:系统中的每一个类都应该只有一个职责. 好处:高内聚.低耦合. 解释说明: 单一职责也就是说我们应该让一个类或一个对象只做一件事情,每个类所要关注的就是自己要完成的职责是什么,能够引起这个类变化的原因也应该只有一个,这也是后面提到的所有的设计模式都会遵守的一个原则. 高内聚:先按照面向对象的封装特性来理解,封装也就是我们说的,应该把一个类或对象它所有相关的属性.方法.行为放到一起,放到一个类中,这样就实现了一个封装的特性.那么内聚,就是一个类里面应该包含它所有的属性和

  • python面向对象编程设计原则之单一职责原则详解

    目录 一,封装 (一)什么是封装 (二)封装与访问 (三)私有化与访问控制 1,属性与方法的私有化 2,变量名压缩 3,方法重载 (四)属性引用:getter.setter与property 二,单一职责原则 (一)一个不满足单一职责原则的例子 (二)单一职责原则 三,封装与单一职责原则 总结 一,封装 封装是面向对象编程思想的重要特征之一. (一)什么是封装 封装是一个抽象对象的过程,它容纳了对象的属性和行为实现细节,并以此对外提供公共访问. 这样做有几个好处: 分离使用与实现.可直接使用公共

  • 单一职责原则_动力节点Java学院整理

    定义:不要存在多于一个导致类变更的原因.通俗的说,即一个类只负责一项职责. 问题由来:类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障. 解决方案:遵循单一职责原则.分别建立两个类T1.T2,使T1完成职责P1功能,T2完成职责P2功能.这样,当修改类T1时,不会使职责P2发生故障风险:同理,当修改T2时,也不会使职责P1发生故障风险. 说到单一职责原则,很多人都会不屑一顾.因为它太简单了.稍有经验的程序员即使

  • java面向对象设计原则之单一职责与依赖倒置原则详解

    目录 单一职责概念 实现 拓展 依赖倒置原则概念 示例 拓展 单一职责概念 不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,否则就应该把类拆分.交杂不清的职责将使得代码牵一发而动全身,导致代码混涩难懂,不易修改.难以扩展和复用.如:以前开发C/S程序中的胖客户端程序,就是将人机交互逻辑.业务加工处理逻辑和数据库操作逻辑混合在一起. 实现 单一职责原则是进行类的划分和封装的基本原则,进行类的具体抽象.尽量做到,类的功能单一和清晰化. 1.根据机能划分,使用封装来创建对象之间的分

  • 简单讲解Java设计模式编程中的单一职责原则

    单一职责原则:一个类,只有一个引起它变化的原因. 为什么需要单一职责原则? 如果一个类有多个原因要去修改它,那么修改一个功能时,可能会让其他功能产生Bug,所以一个类最好只有一个职责.但实际应用中还是比较难实现的,我们只能是尽量符合这个原则. 有时候,开发人员设计接口的时候会有些问题,比如用户的属性和用户的行为被放在一个接口中声明.这就造成了业务对象和业务逻辑被放在了一起,这样就造成了这个接口有两种职责,接口职责不明确,按照SRP的定义就违背了接口的单一职责原则了. 下面是个例子: packag

  • Java设计模式之单一职责原则精解

    1.什么是单一职责原则? 首先我们可以对某个类来说,即一个类应该只负责一项职责.如类A负责两个不同职责: 职责1,职责2.当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1,A2. 我们来看下面这段代码: package com.szh.principle.singleresponsibility; /** * 交通工具类 * 方式1 * 1. 在方式1的run方法中,违反了单一职责原则 * 2. 解决的方案非常的简单,根据交通工具运行方法不同,分解成不同类即可

  • 深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP

    前言 Bob大叔提出并发扬了S.O.L.I.D五大原则,用来更好地进行面向对象编程,五大原则分别是: The Single Responsibility Principle(单一职责SRP) The Open/Closed Principle(开闭原则OCP) The Liskov Substitution Principle(里氏替换原则LSP) The Interface Segregation Principle(接口分离原则ISP) The Dependency Inversion Pr

随机推荐