1
1
# 陆.1.1 单一职责原则
2
2
3
- ## ** 01.什么是单一职责原则? **
3
+ ## ** 01.什么是单一职责原则**
4
4
5
- 单一职责原则,英文缩写** SRP** ,全称Single Responsibility Principle。
5
+ 单一职责原则,英文缩写** SRP** ,全称 ** Single Responsibility Principle** 。
6
6
7
7
原英文定义:
8
8
22
22
23
23
为什么这么说呢?我们来看下面的例子。
24
24
25
- ## 03.OOP职责单一的示例
25
+ ## 03.用JAVA做一段OOP的示例
26
26
27
27
关于单一职责原则的原理,我们就不做过多的解释了。** 重点是职责的划分!重点是职责的划分!重点是职责的划分!** 重要的事情说三遍。下面根据一个示例场景来看看如何划分职责。
28
28
29
29
假定现在有如下场景:国际手机运营商那里定义了生产手机必须要实现的接口,接口里面定义了一些手机的属性和行为,手机生产商如果要生产手机,必须要实现这些接口。
30
30
31
- ### \( 1\) 初始设计
31
+ ### 1\) . 初始设计
32
32
33
33
我们首先以手机作为单一职责去设计接口,方案如下:
34
34
@@ -80,50 +80,47 @@ public class MobilePhone:IMobilePhone
80
80
get{throw new NotImplementedException ();}
81
81
set{throw new NotImplementedException ();}
82
82
}
83
-
84
83
public string ROM
85
84
{
86
85
get{throw new NotImplementedException ();}
87
86
set{throw new NotImplementedException ();}
88
87
}
89
-
90
88
public string CPU
91
89
{
92
90
get{throw new NotImplementedException ();}
93
91
set{throw new NotImplementedException ();}
94
92
}
95
-
96
93
public int Size
97
94
{
98
95
get{throw new NotImplementedException ();}
99
96
set{throw new NotImplementedException ();}
100
97
}
101
-
102
98
public void Charging(ElectricSource oElectricsource)
103
99
{
104
100
throw new NotImplementedException ();
105
101
}
106
-
107
102
public void RingUp()
108
103
{
109
104
throw new NotImplementedException ();
110
105
}
111
-
112
106
public void ReceiveUp()
113
107
{
114
108
throw new NotImplementedException ();
115
109
}
116
-
117
110
public void SurfInternet()
118
111
{
119
112
throw new NotImplementedException ();
120
113
}
121
114
}
122
115
```
123
116
124
- 这种设计有没有问题呢?这是一个很有争议的话题。单一职责原则要求一个接口或类只有一个原因引起变化,也就是一个接口或类只有一个职责,它就负责一件事情,**原则上来说,我们以手机作为单一职责去设计,也是有一定的道理的,因为我们接口里面都是定义的手机相关属性和行为,引起接口变化的原因只可能是手机的属性或者行为发生变化,从这方面考虑,这种设计是有它的合理性的,如果你能保证需求不会变化或者变化的可能性比较小,那么这种设计就是合理的。**但实际情况我们知道,现代科技日新月异,科技的进步促使着人们不断在手机原有基础上增加新的属性和功能。比如有一天,我们给手机增加了摄像头,那么需要新增一个像素的属性,我们的接口和实现就得改吧,又有一天,我们增加移动办公的功能,那么我们的接口实现是不是也得改。由于上面的设计没有细化到一定的粒度,导致任何一个细小的改动都会引起从上到下的变化,有一种“牵一发而动全身”的感觉。所以需要细化粒度,下面来看看我们如何变更设计。
117
+ 这种设计有没有问题呢?这是一个很有争议的话题。
118
+
119
+ 单一职责原则要求一个接口或类只有一个原因引起变化,也就是一个接口或类只有一个职责,它就负责一件事情。** 原则上来说,我们以手机作为单一职责去设计,也是有一定的道理的,因为我们接口里面都是定义的手机相关属性和行为,引起接口变化的原因只可能是手机的属性或者行为发生变化,从这方面考虑,这种设计是有它的合理性的,如果你能保证需求不会变化或者变化的可能性比较小,那么这种设计就是合理的。**
120
+
121
+ 但实际情况我们知道,现代科技日新月异,科技的进步促使着人们不断在手机原有基础上增加新的属性和功能。比如有一天,我们给手机增加了摄像头,那么需要新增一个像素的属性,我们的接口和实现就得改吧,又有一天,我们增加移动办公的功能,那么我们的接口实现是不是也得改。由于上面的设计没有细化到一定的粒度,导致任何一个细小的改动都会引起从上到下的变化,有一种“牵一发而动全身”的感觉。所以需要细化粒度,下面来看看我们如何变更设计。
125
122
126
- ### \( 2 \) 二次变更
123
+ ### 2 \). 二次变更
127
124
128
125
我们将接口细化:
129
126
@@ -173,31 +170,26 @@ public interface IMobilePhoneFunction
173
170
// 手机属性实现类
174
171
public class MobileProperty :IMobilePhoneProperty
175
172
{
176
-
177
173
public string RAM
178
174
{
179
175
get{ throw new NotImplementedException ();}
180
176
set{ throw new NotImplementedException ();}
181
177
}
182
-
183
178
public string ROM
184
179
{
185
180
get{ throw new NotImplementedException ();}
186
181
set{ throw new NotImplementedException ();}
187
182
}
188
-
189
183
public string CPU
190
184
{
191
185
get{ throw new NotImplementedException ();}
192
186
set{throw new NotImplementedException ();}
193
187
}
194
-
195
188
public int Size
196
189
{
197
190
get{throw new NotImplementedException ();}
198
191
set{throw new NotImplementedException ();}
199
192
}
200
-
201
193
public string Pixel
202
194
{
203
195
get{throw new NotImplementedException ();}
@@ -208,27 +200,22 @@ public class MobileProperty:IMobilePhoneProperty
208
200
// 手机功能实现类
209
201
public class MobileFunction :IMobilePhoneFunction
210
202
{
211
-
212
203
public void Charging (ElectricSource oElectricsource )
213
204
{
214
205
throw new NotImplementedException ();
215
206
}
216
-
217
207
public void RingUp ()
218
208
{
219
209
throw new NotImplementedException ();
220
210
}
221
-
222
211
public void ReceiveUp ()
223
212
{
224
213
throw new NotImplementedException ();
225
214
}
226
-
227
215
public void SurfInternet ()
228
216
{
229
217
throw new NotImplementedException ();
230
218
}
231
-
232
219
public void MobileOA ()
233
220
{
234
221
throw new NotImplementedException ();
@@ -252,7 +239,7 @@ public class HuaweiMobile
252
239
253
240
那么,我们如何继续细化接口粒度呢?
254
241
255
- ### \( 3 \) 最终成型
242
+ ### 3 \). 最终成型
256
243
257
244
接口细化粒度设计如下:
258
245
@@ -392,11 +379,11 @@ public class MobilePhoneExtentionFunc : IMobilePhoneExtentionFunc
392
379
393
380
此种设计能解决上述问题,细分到此粒度,这种方案基本算比较完善了。能不能算完美?这个得另说。接口的粒度要设计到哪一步,取决于需求的变更程度,或者说取决于需求的复杂度。
394
381
395
- ## 04 . 勿写万能函数,分解多功能 API
382
+ ## 04 . JavaScript 示例:万能函数
396
383
397
- ### \( 1 \)万能函数
384
+ 接着,我们暂且抛开 JAVA 语言和 OOP ,从 JavaScript 函数的角度来讨论单一职责原则。
398
385
399
- 接着我们可以暂且抛开 OOP ,从 JavaScript 函数的角度来讨论单一职责。新手程序员往往很喜欢写“功能超级强大的复杂的万能函数 ”,以体现自己的编程能力之不俗。
386
+ 还记得吗?新手程序员我们往往很喜欢写“功能超级强大的、复杂的万能函数 ”,以体现自己的编程能力之不俗。
400
387
401
388
```javascript
402
389
// 这是一个功能“超级强大”的函数
@@ -413,7 +400,7 @@ function aBigFunc(param){
413
400
}
414
401
```
415
402
416
- 上面这种多功能函数,理论上只要敢写if 分支,什么任务都完成,俗称“万能函数”。几乎每一个程序员都写过万能函数。万能函数确实能解决问题,而且看上去似乎很强大,甚至还能让总体代码的行数更少一点儿。很多新手程序员,包括笔者刚学编程时也常常以此为借口,堂而皇之地大写特写万能函数 。
403
+ 上面这种多功能函数,理论上只要敢写if 分支,什么任务都完成,俗称“万能函数”。几乎每一个程序员都写过万能函数。万能函数确实能解决问题,而且看上去似乎很强大,甚至还能让总体代码的行数更少一点儿。很多新手程序员包括笔者刚学编程时,也常常以此为借口堂而皇之地大写特写万能函数 。
417
404
418
405
然而,当我们需要修改、新增功能的时候,或者我们接手维护别人的万能函数时,这些万能函数动辄几百行的代码,经常会让我们自己读得头晕眼花,往往是新写的代码只要几分钟,阅读代码却花掉十几分钟;而且随着项目工程变大,代码行数的增加,耗费在读代码上的时间会越来越多。良好的习惯是这样的,将万能函数拆分成功能单一的函数:
419
406
@@ -441,17 +428,14 @@ function doQuest(param){
441
428
442
429
优化之后,复杂的万能函数被分割成很多小函数,以前复杂的细节代码被一个个函数隐藏起来。这样我们以后修改/ 新增这个做任务的函数时候,就可以避免被细节牵绊,大大降低出错的概率;还可以利用IDE 的一些语法结构分析功能,很快速地找到具体的函数位置进行添加/ 修改,无需耗费大量的时间查找、阅读复杂的代码。
443
430
444
- ### \(2 \)多功能API
445
-
446
- // todo
447
-
448
431
## 05 . 总结
449
432
450
433
使用单一职责原则时,没有最合理,只有最合适。理解单一职责原则,最重要的就是掌握好职责划分的粒度,而粒度则取决于需求的粒度。
451
434
452
435
## 06 . 参考文献
453
436
454
437
{% hint style= " info" % }
438
+ [https: // en.wikipedia.org/wiki/Single-responsibility\_principle](https://en.wikipedia.org/wiki/Single-responsibility_principle)
455
439
[https: // zhuanlan.zhihu.com/p/24198903](https://zhuanlan.zhihu.com/p/24198903)
456
440
{% endhint % }
457
441
0 commit comments