Skip to content
On this page

设计模式之策略模式 - 优化 if else 地狱问题

类型单条件模式(一)

js
const orderType = 1
if (orderType === 1) {
  console.log('全部')
  // ...
} else if (orderType === 2) {
  console.log('舆情情感')
  // ...
} else if (orderType === 3) {
  console.log('敏感信息来源')
  //   ...
} else {
  console.log('非敏感来源')
  //   ...
}

const orderTypeSet = {
  1() {
    console.log('全部舆情')
  },
  2() {
    console.log('舆情情感')
  },
  3() {
    console.log('敏感信息来源')
  },
  4() {
    conosle.log('非敏感信息来源')
  }
}

orderTypeSet[orderType]()
const orderType = 1
if (orderType === 1) {
  console.log('全部')
  // ...
} else if (orderType === 2) {
  console.log('舆情情感')
  // ...
} else if (orderType === 3) {
  console.log('敏感信息来源')
  //   ...
} else {
  console.log('非敏感来源')
  //   ...
}

const orderTypeSet = {
  1() {
    console.log('全部舆情')
  },
  2() {
    console.log('舆情情感')
  },
  3() {
    console.log('敏感信息来源')
  },
  4() {
    conosle.log('非敏感信息来源')
  }
}

orderTypeSet[orderType]()

多层条件嵌套逻辑 (一)

多层条件嵌套

如果条件越来越多并且出现嵌套的条件层级

js
const orderType = 1 // 1: 美妆,2:电器,3:家具
const orderWay = 2 // 1:h5,2:app,3:小程序

const strategy = () => {
  // 订单类型+环境类型策略
  const map = new Map([
    [
      {
        orderType: 1,
        orderWay: 1
      },
      () => {
        console.log('美妆订单h5')
      }
    ],
    [
      {
        orderType: 1,
        orderWay: 2
      },
      () => {
        console.log('美妆订单app')
      }
    ],
    [
      {
        orderType: 1,
        orderWay: 3
      },
      () => {
        console.log('美妆订单小程序')
      }
    ],
    [
      {
        orderType: 2,
        orderWay: 1
      },
      () => {
        console.log('电器订单h5')
      }
    ],
    [
      {
        orderType: 2,
        orderWay: 2
      },
      () => {
        console.log('电器订单app')
      }
    ],
    [
      {
        orderType: 2,
        orderWay: 3
      },
      () => {
        console.log('电器订单小程序')
      }
    ],
    [
      {
        orderType: 3,
        orderWay: 1
      },
      () => {
        console.log('家具订单h5')
      }
    ],
    [
      {
        orderType: 3,
        orderWay: 2
      },
      () => {
        console.log('家具订单app')
      }
    ],
    [
      {
        orderType: 3,
        orderWay: 3
      },
      () => {
        console.log('家具订单小程序')
      }
    ]
  ])
  return map
}

const run = (orderType, orderWay) => {
  let action = [...strategy()].filter(
    ([key, value]) => key.orderType === orderType && key.orderWay === orderWay
  )
  action.forEach(([key, value]) => value.call(this))
}

run(orderType, orderWay)
const orderType = 1 // 1: 美妆,2:电器,3:家具
const orderWay = 2 // 1:h5,2:app,3:小程序

const strategy = () => {
  // 订单类型+环境类型策略
  const map = new Map([
    [
      {
        orderType: 1,
        orderWay: 1
      },
      () => {
        console.log('美妆订单h5')
      }
    ],
    [
      {
        orderType: 1,
        orderWay: 2
      },
      () => {
        console.log('美妆订单app')
      }
    ],
    [
      {
        orderType: 1,
        orderWay: 3
      },
      () => {
        console.log('美妆订单小程序')
      }
    ],
    [
      {
        orderType: 2,
        orderWay: 1
      },
      () => {
        console.log('电器订单h5')
      }
    ],
    [
      {
        orderType: 2,
        orderWay: 2
      },
      () => {
        console.log('电器订单app')
      }
    ],
    [
      {
        orderType: 2,
        orderWay: 3
      },
      () => {
        console.log('电器订单小程序')
      }
    ],
    [
      {
        orderType: 3,
        orderWay: 1
      },
      () => {
        console.log('家具订单h5')
      }
    ],
    [
      {
        orderType: 3,
        orderWay: 2
      },
      () => {
        console.log('家具订单app')
      }
    ],
    [
      {
        orderType: 3,
        orderWay: 3
      },
      () => {
        console.log('家具订单小程序')
      }
    ]
  ])
  return map
}

const run = (orderType, orderWay) => {
  let action = [...strategy()].filter(
    ([key, value]) => key.orderType === orderType && key.orderWay === orderWay
  )
  action.forEach(([key, value]) => value.call(this))
}

run(orderType, orderWay)

解决多重嵌套条件地狱

上述的多种嵌套条件的解决方案是比较简单的,现实中很难有这么完美的条件判断出现。接下来见证一下什么叫地狱的风景

ts
const orderType = 1 // 1: 美妆,2:电器,3:家具
const orderWay = 1 // 1:h5,2:app,3:小程序
const orderMoney = 100 // 金额范围划分,0-100,100-1000,1000以上,跳转的订单详情也不相同

if (orderType === 1) {
  if (orderWay === 1) {
    if (0 <= orderMoney && orderMoney < 100) {
      console.log('美妆订单h5-0')
    } else if (orderMoney < 1000) {
      console.log('美妆订单h5-100')
    } else {
      console.log('美妆订单h5-1000')
    }
  } else if (orderWay === 2) {
    if (0 <= orderMoney && orderMoney < 100) {
      console.log('美妆订单app-0')
    } else if (orderMoney < 1000) {
      console.log('美妆订单app-100')
    } else {
      console.log('美妆订单app-1000')
    }
  } else if (orderWay === 3) {
    if (0 <= orderMoney && orderMoney < 100) {
      console.log('美妆订单小程序-0')
    } else if (orderMoney < 1000) {
      console.log('美妆订单小程序-100')
    } else {
      console.log('美妆订单小程序-1000')
    }
  }
} // 条件判断次数太多,所以此处只用了一层条件
const orderType = 1 // 1: 美妆,2:电器,3:家具
const orderWay = 1 // 1:h5,2:app,3:小程序
const orderMoney = 100 // 金额范围划分,0-100,100-1000,1000以上,跳转的订单详情也不相同

if (orderType === 1) {
  if (orderWay === 1) {
    if (0 <= orderMoney && orderMoney < 100) {
      console.log('美妆订单h5-0')
    } else if (orderMoney < 1000) {
      console.log('美妆订单h5-100')
    } else {
      console.log('美妆订单h5-1000')
    }
  } else if (orderWay === 2) {
    if (0 <= orderMoney && orderMoney < 100) {
      console.log('美妆订单app-0')
    } else if (orderMoney < 1000) {
      console.log('美妆订单app-100')
    } else {
      console.log('美妆订单app-1000')
    }
  } else if (orderWay === 3) {
    if (0 <= orderMoney && orderMoney < 100) {
      console.log('美妆订单小程序-0')
    } else if (orderMoney < 1000) {
      console.log('美妆订单小程序-100')
    } else {
      console.log('美妆订单小程序-1000')
    }
  }
} // 条件判断次数太多,所以此处只用了一层条件

我们来简单分析一下上述的条件,可以将相同的策略提取出来。首先环境跟订单类型的组合可以默认已知,所以将金额条件提取出来,当作一组策略返回

ts
const orderType = 1 // 1: 美妆,2:电器,3:家具
const orderWay = 1 // 1:h5,2:app,3:小程序
const orderMoney = 10000 // 金额范围划分,0-100,100-1000,1000以上,跳转的订单详情也不相同

const orderMoneyStrategy = (orderMoney) => {
  // 提取金额策略
  if (0 <= orderMoney && orderMoney < 100) {
    return 1
  } else if (orderMoney < 1000) {
    return 2
  }
  return 3
}

const strategy = () => {
  // 订单类型+环境类型策略
  const map = new Map([
    [
      {
        orderType: 1,
        orderWay: 1,
        orderMoney: 1
      },
      () => {
        console.log('美妆订单h5-0')
      }
    ],
    [
      {
        orderType: 1,
        orderWay: 1,
        orderMoney: 2
      },
      () => {
        console.log('美妆订单h5-100')
      }
    ],
    [
      {
        orderType: 1,
        orderWay: 1,
        orderMoney: 3
      },
      () => {
        console.log('美妆订单h5-1000')
      }
    ]
  ])
  return map
}

const run = (orderType, orderWay, orderMoney) => {
  let action = [...strategy()].filter(
    ([key, value]) =>
      key.orderType === orderType && key.orderWay === orderWay && key.orderMoney === orderMoney
  )
  action.forEach(([key, value]) => value.call(this))
}

run(orderType, orderWay, orderMoneyStrategy(orderMoney))
const orderType = 1 // 1: 美妆,2:电器,3:家具
const orderWay = 1 // 1:h5,2:app,3:小程序
const orderMoney = 10000 // 金额范围划分,0-100,100-1000,1000以上,跳转的订单详情也不相同

const orderMoneyStrategy = (orderMoney) => {
  // 提取金额策略
  if (0 <= orderMoney && orderMoney < 100) {
    return 1
  } else if (orderMoney < 1000) {
    return 2
  }
  return 3
}

const strategy = () => {
  // 订单类型+环境类型策略
  const map = new Map([
    [
      {
        orderType: 1,
        orderWay: 1,
        orderMoney: 1
      },
      () => {
        console.log('美妆订单h5-0')
      }
    ],
    [
      {
        orderType: 1,
        orderWay: 1,
        orderMoney: 2
      },
      () => {
        console.log('美妆订单h5-100')
      }
    ],
    [
      {
        orderType: 1,
        orderWay: 1,
        orderMoney: 3
      },
      () => {
        console.log('美妆订单h5-1000')
      }
    ]
  ])
  return map
}

const run = (orderType, orderWay, orderMoney) => {
  let action = [...strategy()].filter(
    ([key, value]) =>
      key.orderType === orderType && key.orderWay === orderWay && key.orderMoney === orderMoney
  )
  action.forEach(([key, value]) => value.call(this))
}

run(orderType, orderWay, orderMoneyStrategy(orderMoney))

上述就是将两个策略拆开再组合,可以使条件逻辑更加清晰,但是从上述例子也能看出,策略模式在使用过程中并不能减少很多的代码量,并且策略越多,拆分组合的过程就会越复杂

设计模式之策略模式 - 优化 if else 地狱问题 has loaded