likes
comments
collection
share

前端设计模式之其他模式(十)

作者站长头像
站长
· 阅读数 12

职责链模式

  • 一步操作可能多个对象都有机会处理请求,将这些对象连成一条链,并沿着这条链传递该请求
  • 这样就将请求者和处理者、包括多个处理者之间进行了分离
  • 体现在前端就是链式操作
const order500 = (orderType, pay, stock) => {
  if (orderType === 1 && pay === true) {
    console.log("500元定金预购, 得到100优惠券");
  } else {
    order200(orderType, pay, stock); // 将请求传递给200元订单
  }
};

const order200 = (orderType, pay, stock) => {
  if (orderType === 2 && pay === true) {
    console.log("200元定金预购, 得到50优惠券");
  } else {
    orderNormal(orderType, pay, stock); // 将请求传递给普通订单
  }
};

const orderNormal = (orderType, pay, stock) => {
  if (stock > 0) {
    console.log("普通购买, 无优惠券");
  } else {
    console.log("手机库存不足");
  }
};

order500(1, true, 500); // 输出:500 元定金预购, 得到100 优惠券

策略模式

  • 主要解决多个 if...else 或者 switch...case 的问题
  • 每个分支单独处理,相互隔离

遇到大量 if 记住下面的口诀:

  • 短路条件早 return
  • 互斥条件表驱动
  • 嵌套条件校验链
  • 零散条件可组合
// 处理预热价
function prePrice(originPrice) {
  return originPrice * 0.9;
}

// 处理大促价
function onSalePrice(originPrice) {
  return originPrice * 0.8;
}

// 询价,随着时间增长,if肯定会越来越多
function askPrice(tag, originPrice) {
  // 处理预热价
  if (tag === "pre") {
    return prePrice(originPrice);
  }
  // 处理大促价
  if (tag === "onSale") {
    return onSalePrice(originPrice);
  }
}

使用策略模式:

const priceProcessor = {
  pre(originPrice) {
    return originPrice * 0.9;
  },
  onSale(originPrice) {
    return originPrice * 0.8;
  },
};

// 通过标签名去定位
function askPrice(tag, originPrice) {
  return priceProcessor[tag](originPrice);
}

键值对对应:根据 status 显示对应名称:

// 同样也可以使用 map 对象存储
const statusStr = {
  1: "待付款",
  2: "待发货",
  3: "已发货",
  4: "交易完成",
  5: "交易关闭",
  default: "",
};

const getStatus = (status) =>{
  return statusStr[status] || statusStr['default']
}

多个 condition 对应名称:

const onButtonClick = (status, identity) => {
  if (identity == "guest") {
    if (status == 1) {
      //do sth
    } else if (status == 2) {
      //do sth
    } else {
      //do sth
    }
  } else if (identity == "master") {
    if (status == 1) {
      //do sth
    } else if (status == 2) {
      //do sth
    } else {
      //do sth
    }
  }
};

使用策略模式优化:

// 同样也可以使用 map 储存
const actions = {
  guest_1: () => {
    /*do sth*/
  },
  guest_2: () => {
    /*do sth*/
  },
};

const onButtonClick = (identity, status) => {
  let action = actions[`${identity}_${status}`] || actions["default"];
  action();
};

比如某平台的信用分数评级,超过700,就是信用极好,650-700信用优秀,600-650信用良好,550-600信用中等,350-550信用较差

function showGrace(grace) {
  let _level = "";
  if (grace >= 700) {
    _level = "信用极好";
  } else if (grace >= 650) {
    _level = "信用优秀";
  } else if (grace >= 600) {
    _level = "信用良好";
  } else if (grace >= 550) {
    _level = "信用中等";
  } else {
    _level = "信用较差";
  }
  return _level;
}

使用策略模式:

// 用look-up表驱动,把配置数据和业务逻辑分离
function showGrace(grace, level, levelText) {
  for (let i = 0; i < level.length; i++) {
    if (grace >= level[i]) {
      return levelText[i];
    }
  } //如果不存在,那么就是分数很低,返回最后一个
  return levelText[levelText.length - 1];
}
let graceForLevel = [700, 650, 600, 550];
let levelText = ["信用极好", "信用优秀", "信用良好", "信用中等", "信用较差"];

console.log(showGrace(696, graceForLevel, levelText)); // 信用优秀

适配器模式

  • 对外统一(入参、调用方式、出参)
  • axios靠一套 API 不仅能在浏览器端调用,而且在 Node 环境同样适用,靠的就是灵活的适配器使用
  • 类似于耳机转换头,把一个接口转换为另一个接口
// 电源插口
class Source {
  supply() {
    return "220V 电源";
  }
}

// 适配器
class Adapter {
  source = new Source();
  adaptedSupply() {
    const sourceRes = this.source.supply();
    return `${sourceRes} --> 12V 电源`;
  }
}

// 手机使用
const adapter = new Adapter();
const res = adapter.adaptedSupply();
console.log(res);

MVC 和 MVVM

MVC

MVC 原理

  • View 传送指令到 Controller
  • Controller 完成业务逻辑后,要求 Model 改变状态
  • Model 将新的数据发送到 View,用户得到反馈

前端设计模式之其他模式(十)

MVVM

MVVM 直接对标 Vue 即可

  • View 即 Vue template
  • Model 即 Vue data
  • VM 即 Vue 其他核心功能,负责 View 和 Model 通讯

前端设计模式之其他模式(十)

前端设计模式之其他模式(十)