单一职责和开闭原则
一、单一职责原则(Single Responsibility Principle, SRP)
核心思想:一个类 / 模块 / 函数应该只有一个引起它变化的原因
通俗理解:每个代码单元只做一件事,且把这件事做好
JavaScript 示例
违反 SRP 的写法:
javascript
class User {
constructor(name, email) {
this.name = name
this.email = email
}
// 同时负责用户数据存储和发送邮件
saveToDatabase() {
// 数据库存储逻辑...
}
sendWelcomeEmail() {
// 邮件发送逻辑...
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
遵循 SRP 的改造:
javascript
// 拆分职责
class User {
constructor(name, email) {
this.name = name
this.email = email
}
}
class UserRepository {
save(user) {
// 数据库存储逻辑
}
}
class EmailService {
sendWelcomeEmail(user) {
// 邮件发送逻辑
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
应用场景:
- 拆分数据模型与持久化逻辑
- 分离业务逻辑与副作用(如 API 调用)
- React 中的容器组件与展示组件分离
二、开闭原则(Open-Closed Principle, OCP)
核心思想:对扩展开放,对修改关闭
通俗理解:通过增加新代码实现功能扩展,而不是修改已有代码
JavaScript 示例
违反 OCP 的写法:
javascript
class Logger {
log(message, type) {
switch(type) {
case 'file':
// 写文件逻辑
break
case 'database':
// 写数据库逻辑
break
// 每次新增类型都要修改此类
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
遵循 OCP 的改造:
javascript
// 基础抽象
class Logger {
log(message) {
throw new Error('必须实现 log 方法')
}
}
// 具体实现扩展
class FileLogger extends Logger {
log(message) {
// 文件存储逻辑
}
}
class DatabaseLogger extends Logger {
log(message) {
// 数据库存储逻辑
}
}
// 新增日志类型时不修改已有类
class CloudLogger extends Logger {
log(message) {
// 云存储逻辑
}
}
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
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
更灵活的 JS 实现(利用函数式特性):
javascript
const createLogger = (strategy) => ({
log: (message) => strategy(message)
})
const fileStrategy = msg => { /* 文件逻辑 */ }
const dbStrategy = msg => { /* 数据库逻辑 */ }
const fileLogger = createLogger(fileStrategy)
const dbLogger = createLogger(dbStrategy)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
应用场景:
- 支付方式扩展(支付宝 / 微信 / 信用卡)
- 不同数据格式导出(CSV/JSON/Excel)
- 中间件模式(如 Express/Koa)
两大原则的关系
原则 | 关注点 | 典型实现方式 |
---|---|---|
单一职责 | 代码单元的内聚性 | 模块拆分 / 函数职责细化 |
开闭原则 | 系统的扩展性 | 抽象 / 多态 / 策略模式 / 高阶函数 |
协同作用:
- 单一职责是开闭的基础:只有职责单一的对象才容易扩展
- 开闭原则指导架构设计:通过抽象预留扩展点