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