Skip to content

场景

目前需要实现多个tab页面切换,并且tab页存在很多的默认值需要前端进行设置

想法和引入

因为存在大量的默认值需要进行判断,如果采用大量的if-else,那么可能会导致代码比较零散,以后维护起来非常的困难。

所以就可以想到,策略模式,专门用于优化if-else过多的问题

简单来概括一下他的用法:枚举类+Map:抽象为对象/Map,然后 Map 对象直接匹配

具体抽象为map 还是object,可以根据具体情况来进行判断

  1. 枚举出所有需要默认的值
  2. 将他们都放在一个Map里面
  3. 后续需要用用到哪一个,只要get/set就可以了

代码和使用

typescript
/**
 * @description 获取表单的默认值
 * @param param0
 * @returns
 */
export function getDefaultValues({
  materialType,
  materialTypeDesc,
}: GetListValueProps) {
  // 可复用性检查数据
  const availabilityCheckDataMap = {
    ZA10: "KP 无检查",
    ZE50: "KP 无检查",
    ZF60: "KP 无检查",
    ZB20: "02",
    ZC30: "02",
    ZD40: "02",
    ZG70: "02",
    ZJ80: "02",
    ZH90: "02",
  };

  // 项目类别组数据
  const itemCategoryGroupDataMap = {
    ZB20: "NORM",
    ZC30: "NORM",
    ZD40: "NORM",
    ZG70: "NORM",
    ZH90: "NORM",
    ZA10: "ERLA",
    ZF60: "DIEN",
  };

  // MRP类型数据
  const mrpTypeDataMap = {
    ZB20: "PD",
    ZC30: "PD",
    ZD40: "PD",
  };

  // 计划参数文件
  const planningParameterFileDataMap = {
    ZB20: "000001",
    ZC30: materialTypeDesc === "半成品" ? "000001" : "",
  };

  // 价格确定
  const priceDeterminationDataMap = {
    ZC30: materialTypeDesc === "BOM原料" ? "2" : materialTypeDesc === "非BOM原料" ? "2" : "",
    ZC50: materialTypeDesc === "非生产物资" ? "2" : ""
  };

  return {
    // 销售视图默认值
    availabilityCheck: availabilityCheckDataMap[materialType],
    itemCategoryGroup: itemCategoryGroupDataMap[materialType],
    // 生产视图默认值
    mrpType: mrpTypeDataMap[materialType] || "ND", // 默认值为'ND'
    planParamFile: planningParameterFileDataMap[materialType], // 默认值为undefined
    priceDetermination: priceDeterminationDataMap[materialType]
  };
}
  1. 我将获取默认值这个事情封装为一个函数,专门用于获取默认值
  2. 将所有的枚举都按照key-value的格式列出来
  3. 最后将他们返回
typescript
const defaultValues = getDefaultValues({
  materialType: baseView?.materialType,
  materialTypeDesc: baseView?.materialTypeDesc,
}); // 获取所有的默认值

setDefaultData({
  ...initSetting.viewData,
  saleView: {
    ...saleView,
    availabilityCheck:
      saleView?.availabilityCheck || defaultValues.availabilityCheck,
    itemCategoryGroup:
      saleView?.itemCategoryGroup || defaultValues.itemCategoryGroup,
  },
  mrpView: {
    ...mrpView,
    mrpType: mrpView?.mrpType || defaultValues.mrpType,
    usingCheck: mrpView?.usingCheck || defaultValues.availabilityCheck,
  },
  financeView: {
    ...financeView,
    priceDetermination:
      financeView?.priceDetermination || defaultValues.priceDetermination,
  },
});

其实个人感觉,我上面这个代码更像是将代码直接抽离出来,封装为函数,和策略模式有些联系,但不是很大。

或者我们tab页面切换视图的时候,每一个 tab页面都会携带各自的onFinish方法和他们的页面,我们就可以将他们都放到一个onject里面,后续使用只要直接去调用就好

typescript
// 设置维护Items的对应关系
const maintenanceItemsMap = {
  baseView: {
    label: "基础视图",
    children: BasicView(),
    key: "baseView"
  },
  saleView: {
    label: viewLossStatus.lossSaleView ? "销售视图(缺失)" : "销售视图",
    children: SalesMaintenance(),
    onFinish: saleFormSubmit,
    key: "saleMaintenanceView"
  },
  purchaseView: {
    label: viewLossStatus.lossPurchaseView ? "采购视图(缺失)" : "采购视图",
    children: PurchaseMaintenance(),
    onFinish: purchaseFormSubmit,
    key: "purchaseMaintenanceView"
  },
  mrpView: {
    label: viewLossStatus.lossMrpView ? "生产视图(缺失)" : "生产视图",
    children: ProductionMaintenance(),
    onFinish: mrpFormSubmit,
    key: "mrpMaintenanceView"
  },
  financeView: {
    label: viewLossStatus.lossFinanceView ? "财务视图(缺失)" : "财务视图",
    children: FinanceMaintenance(),
    onFinish: financeFormSubmit,
    key: "financeMaintenanceView"
  },
};

// 根据返回的参数,isView和checkedKeys,来显示对应的视图
function getViewItems() {
  const { isView, checkedKeys } = initSetting;
  return checkedKeys.map((key: string) => {
    return {
      key,
      label: maintenanceItemsMap[key].label,
      children: maintenanceItemsMap[key].children,
    };
  });
}

参考链接

一文搞懂策略模式(优化策略模式完全消除if else)_策略模式优化-CSDN博客(易于理解)

前端设计模式之策略模式 - 掘金(评论区)