设计模式七大原则—单一职责原则

基本介绍

在程序设计编写某个类时,应当要求某个类结合业务情况只负责一项职责。如果将多个职责融合在一个类中,那么某个职责的改动,很可能会造成其他职责出现错误。

例如,你将订单和商品的处理写在了同一个A类中,当你去针对订单需求变更改动A类时,那么很可能你的某个改动会影响到商品的某些功能,并且这个影响错误往往在编码时很难发现,直到你程序运行时发现,就为时已晚。所以基于“单一职责原则”,我们应该将负责订单和负责商品的部分,分解为两个单独的类。

通过“单一职责原则”来思考不同代码示例下的表现情况

示例1

 1     //盒子类
 2     class Box
 3     {
 4         /// <summary>
 5         /// 将物品放入盒子
 6         /// </summary>
 7         /// <param name="stuff">物品</param>
 8         public void Lay(string stuff)
 9         {
10             Console.WriteLine($"将{stuff}放入盒子里");
11         }
12     }
13 
14     internal class Program
15     {
16         static void Main(string[] args)
17         {
18             Box box = new Box();
19             box.Lay("");
20             box.Lay("");
21             box.Lay("锤子");
22         }
23     }

从上面的简单代码例子来看,定义的盒子类不仅仅只能安放某一种物品,他是可以安放多种物品(碗、书、锤子),以及后续可能会出现的更多种类。因此,从这个示例的层面来看,这个盒子类实际上就违反了“单一职责原则”。我们来分析下具体原因:

1.盒子负责存放的物品是多种的,这就代表了盒子类出现了多职责的情况;

2.如果某天需要盒子放入鸡蛋,并且为了保护鸡蛋不破损,你将在格子里进行分割一个个小格子,那么此时就会发现,因为要放鸡蛋改造了盒子,却导致书放不进盒子了。

示例2

 1   //碗盒
 2     class BowlBox
 3     {
 4         public void Lay(string Bowl)
 5         {
 6             Console.WriteLine($"将{Bowl}放入碗盒里");
 7         }
 8     }
 9 
10     //工具盒
11     class ToolBox
12     {
13         public void Lay(string Tool)
14         {
15             Console.WriteLine($"将{Tool}放入工具盒里");
16         }
17     }
18 
19     //书盒
20     class BookBox
21     {
22         public void Lay(string book)
23         {
24             Console.WriteLine($"将{book}放入书盒里");
25         }
26     }
27 
28 
29     internal class Program
30     {
31         static void Main(string[] args)
32         {
33             BowlBox bowlBox = new BowlBox();
34             bowlBox.Lay("饭碗");
35             ToolBox ToolBox = new ToolBox();
36             ToolBox.Lay("锤子");
37             BookBox bookBox = new BookBox();
38             bookBox.Lay("");
39         }
40     }

接着示例1的背景,示例2根据每种物品都声明了不同的盒子,直观上来看示例2是符合了“单一职责原则”,因为每个盒子只装一种类型物品。从示例的业务体量来看,我们的实际需要是很小的,就是将一个盒子里放几件东西,但是我们要针对每种物品创建一个类,并且在调用端要针对不同物品声明不同类进行处理,那么对于这个示例的需求体量而言,代码开销是比较大的。

示例3

 1    //盒子类
 2     class Box
 3     {
 4         public void LayBowlGrid(string bowl)
 5         {
 6             Console.WriteLine($"将{bowl}放入盒子里的碗格");
 7         }
 8         public void LayToolGrid(string tool)
 9         {
10             Console.WriteLine($"将{tool}放入盒子里的工具格");
11         }
12         public void LayBookGrid(string book)
13         {
14             Console.WriteLine($"将{book}放入盒子里的书格");
15         }
16     }
17 
18 
19     internal class Program
20     {
21         static void Main(string[] args)
22         {
23             Box box = new Box();
24             box.LayBowlGrid("饭碗");
25             box.LayToolGrid("锤子");
26             box.LayBookGrid("");
27         }
28     }

示例3从抽象层面你可以想象,你根据预先要放入的物品,将一个盒子分割为多个存放物品的格子,对应到代码就是将物品分别通过不同的方法放入,每个方法只负责存在某一种类型的物品。

示例3从类的角度来看并不符合“单一职责原则”,但是它从方法的角度来看是符合“单一职责原则”的。

分解职责的考量

结合以上三个示例的分析情况,实际上在遵守“单一职责原则”,针对类进行多个职责分解时,需要考量到分解后代码消耗的成本,并对比业务功能的体量。如果和本文中的示例情况一样,分解后消耗比较大,并且功能体量不大(类中成员不多),那么我们可以将分解范围从类下层到方法级别,在方法上遵守“单一职责原则”即可。

总结

遵守“单一职责原则”主要可以有以下好处:

1.可以降低类的复杂度,一个类只针对一项职责展开具体的实现。

2.提高类的可读性,可维护性。

3.降低代码变更带来的风险。

“单一职责原则”理解起来并不是很难,难在编程过程中如何时刻警惕自己遵守这个原则,大多数人在实际的工作中,为了更快的交付,往往忽略了“单一职责原则”,这里的“单一职责原则”往往更像是衡量一个程序员品性的标准。

 

 

 

posted @ 2022-04-28 16:38  姜承轩  阅读(321)  评论(0)    收藏  举报