首页 > 代码库 > 设计模式学习笔记(二) 设计基本原则之【单一职责原则】

设计模式学习笔记(二) 设计基本原则之【单一职责原则】

单一职责原则(SRP: Single Responsibility Principle)

名词解释:

1) 职责:是指类变化的原因。

2) 职责扩散:就是因为某种原因,职责P被分化为粒度更细的职责P1和P2。

3) 可变类:是指创建该类的实例后,可以对其属性进行修改。

4)不可变类:是指创建该类的实例后,不可对其属性进行修改。不可变类是线程安全的。

1、应用场景

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

2、解决方案

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

3、优点

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

  • 提高类的可读性,提高系统的可维护性。

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

  • 提供重用基础:代码块独立,功能单一,可以容易地重用。

  • 提供可扩展性 :依赖别的单元提供的接口,便于扩展。

4、缺点

如果严格的遵循单一职责原则,即所有的类均只负责一项职责,开发者面对的将是巨量的类(类的爆炸),如果没有一个清晰的类管理方法,势必降低系统的可读性和可维护性。

我们不可能针对每个类都设计原子级的职责。那么就会牵涉到职责的组合和划分,我们很难建立一个标准来界定如何对职责进行合理的划分。职责的大小怎么定义是个难题,什么样的职责放在一起是好的内聚也不好定义。

实际项目应用中很少能够实现单一职责原则,必须考虑可变因素与不可变因素的影响和开发效率的问题。

5、实践及示例

一般来说,接口的设计需严格遵守单一职责原则。如下图说所示,我们定义一个文件操作的接口,实现文件的基本操作

技术分享

代码如下:

技术分享
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 
 5 namespace LoadBalan
 6 {
 7      public  interface IFileOperator
 8     {        
 9         void Open(string fileName);
10         void Write(string fileName,byte[] fileData);
11         byte[] Read();
12         void Save(string fileName);
13         void Close(string fileName);         
14     }
15 
16     class DisplayFile : IFileOperator
17     {
18         public void Open(string fileName)
19         {
20 
21         }
22 
23         public void Write(string fileName, byte[] fileData)
24         {
25         }
26         public byte[] Read() {
27 
28             return null ;
29         }
30         public void Save(string fileName)
31         {
32 
33         }
34        public void Close(string fileName)
35         {
36 
37         }
38     }
39     class SaveFile : IFileOperator
40     {
41         public void Open(string fileName)
42         {
43 
44         }
45 
46         public void Write(string fileName, byte[] fileData)
47         {
48         }
49         public byte[] Read()
50         {
51 
52             return null;
53         }
54         public void Save(string fileName)
55         {
56 
57         }
58         public void Close(string fileName)
59         {
60 
61         }
62     }
63 }
View Code

我们可以看到,IFileOperator接口包含了一系列的操作,而我们的DisplayFile类和SaveFile类都只是用到其中一部分操作,但都要实现该接口中所有的操作,造成大量的代码冗余,也影响程序的可读性。根据单一职责原则,我们做如下改进:

技术分享

代码如下(设计不一定合理,只是为了说明单一职责原则):

技术分享
using System;
using System.Collections.Generic;
using System.Text;

namespace LoadBalan
{
    class Lesson_SRP02
    {
        public interface IFileOperator
        {
            void Open(string fileName);           
            void Close(string fileName);
        }
        public interface IFileRead
        {    
            byte[] Read();         
        }
        public interface IFileSave
        {
           
            void Write(string fileName, byte[] fileData);           
            void Save(string fileName);
       
        }

        class DisplayFile : IFileOperator,IFileRead
        {
            public void Open(string fileName)
            {

            }
        
            public byte[] Read()
            {

                return null;
            }
           
            public void Close(string fileName)
            {

            }
        }
        class SaveFile : IFileOperator
        {
            public void Open(string fileName)
            {

            }

            public void Write(string fileName, byte[] fileData)
            {
            }
            
            public void Save(string fileName)
            {

            }
            public void Close(string fileName)
            {

            }
        }
    }
}
View Code

这样,DisplayFile类与SaveFile类里就没有冗余代码,各自只实现自己所需的功能。

 

设计模式学习笔记(二) 设计基本原则之【单一职责原则】