zoukankan      html  css  js  c++  java
  • 01-单一职责原则(SPR)

    1. 背景

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

    2. 定义

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

    3. 宏观上

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

    4. 补充两个概念

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

    5. 案例

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

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

     1  public class Animal
     2     {
     3         public string myName { get; set; }
     4 
     5         private string _name = null;
     6         public Animal()
     7         {
     8 
     9         }
    10         public Animal(string name)
    11         {
    12             this._name = name;
    13         }
    14 
    15         //封装呼吸空气的方法
    16         public void BreathAir()
    17         {
    19               Console.WriteLine(this._name + "呼吸空气");
    21         }
    22     }

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

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

     1    public void BreathAir()
     2         {
     3             if (this._name.Equals(""))
     4             {
     5                  Console.WriteLine(this._name + "呼吸水");   //违背了方法级别的单一职责
     6             }
     7             else
     8             {
     9                 Console.WriteLine(this._name + "呼吸空气");
    10             }
    11         }

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

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

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

     1   public class WaterAnimal
     2     {
     3          private string _name = null;
     4          public WaterAnimal(string name)
     5         {
     6             this._name = name;
     7         } 
     8         //封装呼吸水的方法
     9         public void BreathWater()
    10         {
    11             Console.WriteLine(this._name + "呼吸水");
    12         }
    13     }

     综合调用:

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

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

     1         /// <summary>
     2         /// 利用委托的插件式编程
     3         /// </summary>
     4         public static void show2()
     5         {
     6             Console.WriteLine("------------------下面是利用委托来解决--------------------");
     7             Animal animal1 = new Animal() { myName = "" };
     8             Animal animal2 = new Animal() { myName = "" };
     9             Animal animal3 = new Animal() { myName = "" };
    10             Action<Animal> act1 = Utils.BreathWater;
    11             Action<Animal> act2 = Utils.BreathAir;
    12             act1.Invoke(animal1);
    13             act1.Invoke(animal2);
    14             act2.Invoke(animal3);
    15         }

    6. 单一职责原则的好处

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

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

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

    7. 我的总结

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

  • 相关阅读:
    Consul负载均衡策略记录
    ASP NET CORE开发优化相关专用随笔
    .NET CORE 3.1配置文件读取方式
    CentOS 8 安装.NET CORE 3.1 发布以及运行
    CORE EF生成ORACLE数据库模型报错问题记录
    【转载】一名程序员十年技术之路的思考与感悟
    iview-admin部署linux nginx报500错误的问题记录
    [转]浅谈账号系统设计
    C#使用phantomjs,爬取AJAX加载完成之后的页面
    nginx触屏版跟PC的代理设置
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/7101344.html
Copyright © 2011-2022 走看看