设计模式之单一职责原则

Posted 爱分享的小九

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之单一职责原则相关的知识,希望对你有一定的参考价值。

今天小九上了设计模式的课,小九就整理了一些资料来帮助你们来理解:

今天就讲一下设计模式的原则吧!

面向对象的设计原则:

了解的概念:

  • 软件的可维护性:指软件能够被理解,改正,适应及扩展的难以程度
  • 软件的可复用性:指软件能够被复用使用的难以程度

七个面向对象的设计原则:

  • 单一职责原则:一个对象应该只包含一个单一的职责,而且该职责被完整的封装在一个类中

  • 开闭原则:软件实体应当对扩展开放,对修改关闭

  • 里氏代换原则:所有引用基类的地方必须能够透明的使用其子类对象

  • 依赖倒转原则:高层模块不依赖于底层模块,他们都应该依赖于抽象,抽象不应该依赖于细节,细节应该依赖于抽象。

  • 接口隔离原则:客户端不应该依赖那些不需要的接口

  • 合成复用原则:优先使用对象的组合,而不是继承来达到复用的目的

  • 迪米特法则:每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

单一职责原则

  •  public class Animal
      {
           public void breathe(String animal)
          {
               Console.WriteLine("呼吸空气"+animal);
          }
      }
       public class Program
      {
           static void Main(string[] args)
          {
               Animal animal = new Animal();
               animal.breathe("牛");
               animal.breathe("羊");
               animal.breathe("猪");
          }
      }

    运行结果为:

    呼吸空气牛
    呼吸空气羊
    呼吸空气猪

    如果程序上线后,发现问题了,并不是所有的动物都呼吸空气的。因此需要修改Animal类分为陆生动物类和水生动物类:(代码如下)

     /// <summary>
       /// 水生动物
       /// </summary>
       public class Aquatic
      {
           public void breathe(String animal)
          {
               Console.WriteLine(animal+"呼吸水");
          }
    }
       /// <summary>
       /// 陆生动物
       /// </summary>
       public class Terrestrial
      {
           public void breathe(String animal)
          {
               Console.WriteLine(animal+"呼吸空气");
          }
      }
       public class Program
      {
           static void Main(string[] args)
          {
               Terrestrial animal = new Terrestrial();
               animal.breathe("牛");
               animal.breathe("羊");
               animal.breathe("猪");
               Aquatic aquatic = new Aquatic();
               aquatic.breathe("鱼");
               Console.ReadKey();
          }
      }

    运行结果为:

    牛呼吸空气
    羊呼吸空气
    猪呼吸空气
    鱼呼吸水

    我们会发现这样的修改花销很大,除了将原来的类分解之外,还需要修改客户端。而直接修改类Animal来达成目的虽然违背了单一职责原则,但花销却小的多,代码如下:

    public class Animal
      {
           public void breathe(String animal)
          {
               if ("鱼".Equals(animal))
                   Console.WriteLine("呼吸空气" + animal);
               else
                   Console.WriteLine(animal + "呼吸空气");
          }
      }
    static void Main(string[] args)
          {
               Terrestrial animal = new Terrestrial();
               animal.breathe("牛");
               animal.breathe("羊");
               animal.breathe("猪");
               animal.breathe("鱼");
               Console.ReadKey();
          }

    可以看到,这种修改方式要简单的多。但是却存在着隐患:有一天需要将鱼分为呼吸淡水的鱼和呼吸海水的鱼,则又需要修改Animal类的breathe方法,而对原有代码的修改会对调用“猪”“牛”“羊”等相关功能带来风险,也许某一天你会发现程序运行的结果变为“牛呼吸水”了。这种修改方式直接在代码级别上违背了单一职责原则,虽然修改起来最简单,但隐患却是最大的。还有一种修改方式:

    public class Animal
      {
           public void breathe(String animal)
          {
               Console.WriteLine(animal+"呼吸空气");
          }
           public void breathe1(String animal)
          {
               Console.WriteLine(animal + "呼吸水");
          }
      }
    public class Program
      {
           static void Main(string[] args)
          {
               Animal animal = new Animal();
               animal.breathe("牛");
               animal.breathe("羊");
               animal.breathe("猪");
               animal.breathe("鱼");
               Console.ReadKey();
          }
      }

    结果:

    牛呼吸空气
    羊呼吸空气
    猪呼吸空气
    鱼呼吸空气

    可以看到,这种修改方式没有改动原来的方法,而是在类中新加了一个方法,这样虽然也违背了单一职责原则,但在方法级别上却是符合单一职责原则的,因为它并没有动原来方法的代码。这三种方式各有优缺点,那么在实际编程中,采用哪一种呢?其实这真的比较难说,需要根据实际情况来确定。我的原则是:只有逻辑足够简单,才可以在代码级别上违反单一职责原则;只有类中方法数量足够少,才可以在方法级别上违反单一职责原则;

    小九今天就写到这里,以后会陆续发出其他原则。

以上是关于设计模式之单一职责原则的主要内容,如果未能解决你的问题,请参考以下文章

设计模式(六大原则之单一职责)

设计模式面向对象设计原则之单一职责原则

软件设计原则之 单一职责

设计原则之单一职责原则

设计原则之单一职责原则

设计原则之单一职责原则