图解你身边的 SOLID 原则 - JS 实例版

 

S - 单一职责原则

例子

我们假设需要验证一个表单,然后将用户保存到数据库中。

不推荐

/**
 * 这个函数的名字就明显违背了单一职责原则
 * 对于表单的验证和用户创建被耦合在一起了
 * 这样写是不推荐的!
 */
function validateAndSaveUser (req) {   
  // 调用外部函数来验证用户表单
  const isFormValid = validateForm(req.name, req.password, req.email)
  // 如果表单合法
  if (isFormValid) {
    doCreateUser(req.name, req.password, req.email) // 创建用户的具体实现
  }
}

推荐

// 验证请求的函数
function validateRequest (req) {
  // 调用外部函数来验证用户表单
  const isFormValid = validateForm(req.name, req.password, req.email)
  // 如果表单合法
  if (isFormValid) {
    createUser(req) // 在另一个模块中实现
  }
}
// 仅仅用来将用户存储到数据function createUser (req) {
  doCreateUser(req.name, req.password, req.email) // 具体实现代码
}

上面的修改虽然看起来很小,但是将验证逻辑和用户创建逻辑进行了解耦,而用户创建貌似是个会经常更改的功能,这就为将来的修改提供了便利。

 

O - 开闭原则

例子

假设我们有以下的权限验证函数:

const roles = ["ADMIN", "USER"]
function checkRole (user) {
  if (roles.includes(user.role)) {
    return true
  }
  return false
}
// 角色校验
checkRole("ADMIN") // true
checkRole("Savo") // false

如果我们想要添加一个超级管理员,为了不修改之前的代码(或者说我们本来就无法修改遗留代码),我们可以添加一个新增权限函数:

// 此处的代码无法修改!
const roles = ["ADMIN", "USER"]
function checkRole (user) {
  if (roles.includes(user.role)) {
    return true
  }
  return false
}
// 此处的代码无法修改!
// 我们可以定义一个函数专门用来新增角色
function addRole (role) {
  roles.push(role)
}
// 调用新函数来添加角色
addRole("SUPERUSER")
// 验证角色
checkRole("ADMIN") // true
checkRole("Savo") // false
checkRole("SUPERUSER") // true

 

L - 里氏替换原则

例子

下面以工程师为例子,初级工程师其实就可以被高级工程师替换掉。(没毛病==)

class Engineer {
  constructor (coder) {
    this.coder = coder
    this.writeCode = function () {
      console.log("Coding") // 工程师都会写代码
    }
  }
  // 初级工程师
  Simple (coder) {
    this.writeCode(coder)
  }
  // 高级工程师
  Pro (coder) {
    this.writeCode(coder)
    console.log("Design Architecture") // 高级工程师还需要设计架构~
  }
}
const a = new Engineer("Savokiss")
a.Simple()
// 输出:
// Coding
a.Pro()
// 输出: 
// Coding 
// Design Architecture... 

 

I - 接口隔离原则

例子

不推荐

// 什么情况下都进行验证
class User {
  constructor (username, password) {
    this.initUser(username, password)
  }

  initUser (username, password) {
    this.username = username
    this.password = password
    this.validateUser()
  }

  validateUser () {
    console.log("验证中...") // 添加验证逻辑
  }
}
const user = new User("Savokiss", "123456")
console.log(user)
// 验证中...
// User {
//   validateUser: [Function: validateUser],
//   username: 'Savokiss',
//   password: '123456'
// }

推荐

// 将验证当做一个可选接口
class User {
  constructor (username, password, validate) {
    this.initUser(username, password, validate)
    if (validate) {
      this.validateUser()
    } else {
      console.log("不需要验证逻辑")
    }
  }
  
  initUser (username, password, validate) {
    this.username = username
    this.password = password
    this.validate = validate
  }
  
  validateUser () {
    console.log("验证中...") 
  }
}

// 需要验证的用户
console.log(new User("Savokiss", "123456", true))

// 验证中...
// User {
//   validateUser: [Function: validateUser],
//   username: 'Francesco',
//   password: '123456',
//   validate: true
// }

// 不需要验证的用户
console.log(new User("Guest", "guest", false))

// 不需要验证逻辑
// User {
//   validateUser: [Function: validateUser],
//   username: 'guest',
//   password: 'guest',
//   validate: false
// }

 

D - 依赖倒置原则

例子

不推荐

// http 请求依赖了 setState 函数,即依赖了一个细节
http.get("http://address/api/examples", (res) => {
  this.setState({
    key1: res.value1,
    key2: res.value2,
    key3: res.value3
  })
})

推荐

// http 请求
const httpRequest = (url, state) => {
  http.get(url, (res) => state.setValues(res))
}

// 在另一个函数中设置状态
const state = {
  setValues: (res) => {
    this.setState({
      key1: res.value1,
      key2: res.value2,
      key3: res.value3
    })
  }
}
// 请求时,将 state 作为抽象注入进去
httpRequest("http://address/api/examples", state)

品牌vi设计公司http://www.maiqicn.com 办公资源网站大全https://www.wode007.com

总结

SOLID 原则的主要目标是让任何软件都应该更容易更改,并且更易于理解。

SOLID 原则同时也让你的代码:

  • 更加易于理解
  • 更加易于扩展,同时减少 bug
  • 隔离抽象和实现
  • 更加易于替换实现
  • 更加易于测试

好啦~ 希望本文对你有帮助~

posted @ 2020-09-19 14:22  笑人  阅读(555)  评论(0编辑  收藏  举报