单一职责原则
一个类只负责完成一个职责或者功能。不要设计大而全的类,要设计粒度小、功能单一的类。单一职责原则是为了实现代码高内聚、低耦合,提高代码的复用性、可读性、可维护性。
如何判断类的职责是否足够单一?
不同的应用场景、不同阶段的需求背景、不同的业务层面,对同一个类的职责是否单一,可能会有不同的判定结果。实际上,一些侧面的判断指标更具有指导意义和可执行性,比如,出现下面这些情况就有可能说明这类的设计不满足单一职责原则:
- 类中的代码行数、函数或者属性过多;
- 类依赖的其他类过多,或者依赖类的其他类过多;
- 私有方法过多;
- 比较难给类起一个合适的名字;
- 类中大量的方法都是集中操作类中的某几个属性。
优势
- 类的复杂性降低,实现什么职责都有清晰明确的定义
- 可读性提高,复杂性降低,那当然可读性提高了
- 可维护性提高,可读性提高,那当然更容易维护了
- 变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助
总结
单一职责原则通过避免设计大而全的类,避免将不相关的功能耦合在一起,来提高类的内聚性。同时,类职责单一,类依赖的和被依赖的其他类也会变少,减少了代码的耦合性,以此来实现代码的高内聚、低耦合。但是,如果拆分得过细,实际上会适得其反,反倒会降低内聚性,也会影响代码的可维护性。
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class UserModifyImpl : UserModify { override fun modifyUserPassword(user: User, password: String) { user.password = password }
override fun modifyUserName(user: User, name: String) { user.name = name }
}
interface UserModify {
fun modifyUserPassword(user: User, password: String)
fun modifyUserName(user: User, name: String) }
data class User( var password: String, var name: String, )
|
- 假设我们让小明去倒垃圾,小红去买菜,小红回来后再叫小红去洗碗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| class XiaoMing : TakeOutTheTrash { override fun doPourGarbage() { println("小明 倒垃圾") } }
class XiaoHong : GroceryShopping, WashingUp { override fun doShopping() { println("小红 买菜") }
override fun doWashingUp() { println("小红 洗碗") } }
interface GroceryShopping {
fun doShopping() }
interface TakeOutTheTrash {
fun doPourGarbage() }
interface WashingUp {
fun doWashingUp() }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
class UserRegister{ fun doRegister(user: User){} }
class UserLogin{ fun doLogin(user: User){} }
class UserLogout{ fun doLogout(user: User){} }
data class User( var password: String, var name: String, )
|