首页 > 代码库 > 设计模式学习笔记(二) 设计基本原则之【单一职责原则】
设计模式学习笔记(二) 设计基本原则之【单一职责原则】
单一职责原则(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 }
我们可以看到,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) { } } } }
这样,DisplayFile类与SaveFile类里就没有冗余代码,各自只实现自己所需的功能。
设计模式学习笔记(二) 设计基本原则之【单一职责原则】