表驱动法

凡事可以通过逻辑语句来选择的事物,都可以通过 查表法 来解决,对于简单的情况,逻辑语句更为简单、直白,但是随着选项越来越多,表驱动法就显得更容易维护

enum ErrorCode {
  OK = 200,
  BAD_REQUEST = 400,
  UNAUTHORIZED = 401,
  NOT_FOUND = 404,
  INTERNAL_SERVER_ERROR = 500,
}
 
function handleOk() {}
 
function handleBadRequest() {}
 
function handleUnauthorized() {}
 
function handleNotFound() {}
 
function handleInternalServerError() {}
 
function errorHandler(code: ErrorCode) {
  switch (code) {
    case ErrorCode.OK:
      handleOk();
      break;
    case ErrorCode.BAD_REQUEST:
      handleBadRequest();
      break;
    case ErrorCode.UNAUTHORIZED:
      handleUnauthorized();
      break;
    case ErrorCode.NOT_FOUND:
      handleNotFound();
      break;
  }
}

上面的写法充斥着非常多的 switch 语句,如果后期随着需求和选项的增加,switch 语句会变得越来越长,这时候可以使用 表查找法 来优化

const handleMap = new Map<ErrorCode, () => void>([
  [ErrorCode.OK, handleOk],
  [ErrorCode.BAD_REQUEST, handleBadRequest],
  [ErrorCode.UNAUTHORIZED, handleUnauthorized],
  [ErrorCode.NOT_FOUND, handleNotFound],
  [ErrorCode.INTERNAL_SERVER_ERROR, handleInternalServerError],
]);
 
function errorHandler(code: ErrorCode) {
  const handle = handleMap.get(code);
  handle();
}

CleanShot 2024-01-13 at 15.37.12@2x.png

逻辑倒置

function handleErr(err) {
  if (error) {
    if (error.code === 0) {
      if (error.status === -1) {
        // ...
      }
    }
  }
}
 
function handleErr(err) {
  if (!err)
    throw new Error('err is required');
  if (!err.code)
    throw new Error('err.code is required');
  if (!err.status)
    throw new Error('err.status is required');
  
  // do something...
}

一些第三方的库提供了类似断言的功能,例如 zod,使用时不需要单独判断验证是否正确,zod 本身会抛出错误
CleanShot 2024-01-13 at 15.42.17@2x.png

面向对象

在面向对象编程中,多态调用其实就类似于 switch 分支,但是多态恰恰又可以把分支逻辑完美的隐藏起来,利用面向对象的多态,加上简单工厂,往往可以将分支逻辑独立处理,让主逻辑更加清晰

for (let order of orders) {
  switch (order.promotionMethod) {
    case "FullReduction":
      // 满减
      processFullReduction(order);
      break;
    case "FullGift":
      // 满赠
      processFullGift(order);
      break;
    case "CouponBack":
      // 反券
      processCouponBack(order);
      break;
    default:
      throw new Error();
  }
}
 
// 简单工厂
class PromotionFactory {
  static create(order) {
    switch (order.promotionMethod) {
      case "FullReduction":
        return new FullReductionPromition();
      case "FullGift":
        return new FullGiftPromotion();
      case "CouponBack":
        return new CouponBackPromotion();
      default:
        throw new Error();
    }
  }
}
 
for (let order of orders) {
  let promotion = PromotionFactory.create(order);
  promotion.process();
}

CleanShot 2024-01-13 at 17.35.06@2x.png

特定的场景还可以通过设计模式来解决
例如常见的微波炉的例子
CleanShot 2024-01-13 at 17.42.44@2x.png

这种场景下可以使用状态模式来解决,每个状态对应的操作封装在一起。由多态来选择相应的状态,这样条件语句就可以彻底删除了
CleanShot 2024-01-13 at 17.43.56@2x.png

高阶函数

CleanShot 2024-01-13 at 17.44.36@2x.png

空值判断

CleanShot 2024-01-13 at 17.45.18@2x.png