小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金
最近在学习六大设计原则,醍醐灌顶,现在把自己的感受简单记录一下。
定义
单一功能原则(Single responsibility principle)规定每个类都应该有一个单一的功能,并且该功能应该由这个类完全封装起来。所有它的(这个类的)服务都应该严密的和该功能平行(功能平行,意味着没有依赖)。
通俗点说,也就是一个类只负责一种职责的工作,不存在多个原因使得一个类发生变化。
优点
- 类的复杂度降低,一个类只负责一个功能,其逻辑要比负责多项功能简单的多;
- 类的可读性增强,阅读起来轻松;
- 可维护性强,一个易读、简单的类自然也容易维护;
- 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。
例子
这里就拿1个出名游戏做一下例子,如有雷同,纯属巧合哈。假设每一个召唤师,都可以拥有3个英雄,这时候我们可以定义一个Role的类,写上getheros方法
代码如下:
class Role {
func getheros() -> [String] {
return ["亚瑟", "后裔", "妲己"]
}
}
这很简单是吧,这时候产品过来说,需求要变更了,加1个vip和平民的2种角色,vip1~vip7要多1个英雄。vip8以后,要多2个英雄。
好,这时候我们直接弄一个枚举来定义角色,用swit遍历枚举来返回英雄。
代码如下:
enum IDE {
case vip(Int)
case pingmin
}
class Role {
func getheros(ide: IDE) -> [String] {
switch ide {
case let .vip(number):
if (number >= 8) {
return ["亚瑟", "后裔", "妲己", "赵云", "武则天"]
}else {
return ["亚瑟", "后裔", "妲己", "赵云"]
}
case .pingmin:
return ["亚瑟", "后裔", "妲己"]
}
}
}
这么看,也不是很难是吧。
随着需求的迭代,这时候产品有说,角色添加打架功能,平民一开始战斗力为0,vip1~vip7为10,vip8以后为20。
这时候,其实我们感觉有点不对劲了,但在原来基础上好像也不是改动很大,好,再改
class Role {
func getheros(ide: IDE) -> [String] {
switch ide {
case let .vip(number):
if (number >= 8) {
return ["亚瑟", "后裔", "妲己", "赵云", "武则天"]
}else {
return ["亚瑟", "后裔", "妲己", "赵云"]
}
case .pingmin:
return ["亚瑟", "后裔", "妲己"]
}
}
func fight(ide: IDE) -> Int {
switch ide {
case let .vip(number):
if (number >= 8) {
return 20
}else {
return 10
}
case .pingmin:
return 0
}
}
}
这时候,产品的需求,又TM增加了,vip的角色拥有显示皮肤功能,而且vip8以后的才可以有建群功能。
如果在这上面代码基础下,是不是又要添加两个方法,再枚举遍历去输出相应的内容。这时候我们已经意识到Role这个类越来越臃肿了,那后面产品再改动或者增加,感觉就不好维护了。
单一职责原则是说一个类只负责一种职责的工作,很明显这里Role类,已经负责很多种职责了。平民有3个英雄,vip1~vip7有4个英雄,vip8后面有5个英雄,这才是单一职责原则,而不是角色拥有3或4或5个英雄。
好,那我们就可以建一个类为pinmin,1个类是vip1,vip2...,每个身份都拥有自己的功能。
class pingmin: Role {
override func getheros() -> [String] {
return ["亚瑟", "后裔", "妲己"]
}
override func fight() -> Int {
return 0
}
}
class Vip1: Role {
override func getheros() -> [String] {
return ["亚瑟", "后裔", "妲己", "赵云"]
}
override func fight() -> Int {
return 10
}
func showPiFu() {
print("显示皮肤")
}
}
class Vip8: Role {
override func getheros() -> [String] {
return ["亚瑟", "后裔", "妲己", "赵云", "武则天"]
}
override func fight() -> Int {
return 20
}
func havaPiFu() {
print("显示皮肤")
}
func createGroup() {
print("建群")
}
}
那后面,如果哪种身份又需要添加功能,我们就可以直接在该类上添加即可,这样就完全不会影响到其它类,耦合度也大大降低了,代码也不会全部臃肿在1个类当中。
总结
单一职责原则是六大设计原则中算是比较简单的了,但管中窥豹,实际开发中,随着功能的增多,要及时注意,看是否有违背一个类只负责一种职责的工作,能重构就马上重构,不然代码量多了后,想重构又难,继续有原来基础上维护又难。
如果以上说法有不足之处,欢迎留意。