# 模拟场景
开完会后,经理给你分配了一个任务,让你给管理系统开发一个针对不同的用户设置不同的权限的功能。假设目前的角色有管理员、前端开发人员、后端开发人员。
你可能会写出下面这样的代码:
function setPermissions(role) {
if (role === 'admin') {
// ...
}else if (role === 'back') {
// ...
}else if (role === 'front') {
// ...
}
}
虽然猛一看好像没什么问题,功能也能正常运行,但它首先违背了设计模式里的 ”单一职责“ 原则。上述代码将不同角色的权限内容都设置在了一个函数中,导致设置权限的函数变的十分臃肿,修改的话也不好修改,可谓牵一发而动全身,下面我们针对 “单一职责” 原则对代码进行优化。
function adminPermissions() {
// ...
}
function backPermissions(){
// ...
}
function frontPermissions() {
// ...
}
function setPermissions() {
if (role === 'admin') {
adminPermissions()
}else if (role === 'back') {
backPermissions()
}else if (role === 'front') {
frontPermissions()
}
}
上面我们将不同用户的权限封装到了不同的函数中,如果某个用户的权限内容发生了变化,只需要修改对应的函数即可。
其次它还违反了 ”开放封闭“ 原则。假设现在又新增了测试人员,你该怎么办呢?你可能会想,那有什么呢?直接在在下面增加一个判断酒店就好了呀,你可能会写出下面这样的代码:
function setPermission(role) {
if (role === 'admin') {
// ...
}else if (role === 'back') {
// ...
}else if (role === 'front') {
// ...
}else if (role === 'tester') {
// ...
}
}
上面我们给测试人员增加了权限操作,但是是通过直接修改 setpermission 方法实现的。可以看出它违反了 ”开放封闭“(对扩展开放,对修改封闭)原则。
下面我们来针对 ”开放封闭“ 原则对代码进行优化。
我们先来看一下最开始的代码主要是实现的什么功能?我们通过 if...else if... 来判断不同的角色,并给予不同的权限,好像是一个映射关系。在 JS 中有没有现成的映射关系数据结构呢?答案是有的,就比如对象。我们可以使用对象来优化上面的代码。
const permissions = {
admin(){
// ...
},
back(){
// ...
},
front(){
// ...
},
tester(){
// ...
}
}
function setPermissions(role) {
return permissions[role]()
}
上面我们就针对 “开放封闭” 原则对代码进行了优化。通过上面的优化,我们可以看到设置权限的函数里面只有一行代码,职责非常单一。当需要给新的用户设置权限的时候,我们只需要扩展permissions这个对象即可。比如,我们需要给运营同学添加权限:
permissions.operations = function() {
// ...
}
# 策略模式
上面的重构过程就是对策略模式的一种应用。下面我们来看一下策略模式的定义:
策略模式
定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
从上面的例子我们可以看出,设置权限的逻辑对应的就是定义里的 “算法” ,对各个用户的权限进行抽离对应的就是定义里的 “封装” ,使用对象进行映射,对应了定义里的 “替换” 。