遇到一道设计模式的面试题,各位大佬看下如何解决,题目要求是优化这段业务代码?

遇到一道设计模式的面试题,各位大佬看下如何解决,题目要求是优化这段业务代码
条件是布尔值或者函数返回值,cb 是函数

function runTask() {
  if(条件A){
    cbA()
    if(条件B){
      cbB()
    }
  }
  if(条件C){
    cbC()
    if(条件D){
      cbD()
    }
  }
}
阅读 2k
13 个回答
function runTask() {
    ;(
        [
            [conditionA, cbA],
            [conditionA && conditionB, cbB],
            [conditionC, cbC],
            [conditionC && conditionD, cbD]
        ] as const
    ).forEach(([condition, callback]) => condition && callback())
}

优化的方向有给吗?

我暂时想不出什么优化方案了,蹲一波。

这个方向是可读性:

function runTask() {
  if (条件A) {
    条件B ? cbB() : cbA()
  }

  if (条件C) {
    条件D ? cbD() : cbC()
  }
}

这个方向是拓展性:

function runTask(params) {
  const items = [
    {
      validator: (params) => 条件A,
      func: () => {
        // cbA
      },
    },
    {
      validator: (params) => 条件A && 条件B,
      func: () => {
        // cbB
      },
    },
    {
      validator: (params) => 条件C,
      func: () => {
        // cbC
      },
    },
    {
      validator: (params) => 条件C && 条件D,
      func: () => {
        // cbD
      },
    },
  ];

  items.forEach((item) => {
    if (item.validator(params)) {
      item.func();
    }
  });
}
function A() {
  console.log("execute task A");
}
function B() {
  console.log("execute task B");
}
function C() {
  console.log("execute task C");
}
function D() {
  console.log("execute task D");
}
function runTask() {
  const conditionA = () => true;
  const conditionB = () => false;
  const conditionC = () => false;
  const conditionD = () => true;
  const processFlows = [
      [
        [conditionA, A],
        [conditionB, B]
      ],
      [
        [conditionC, C],
        [conditionD, D]
      ] 
    ];
  
  for(const flow of processFlows) {
    for(const [condition, task] of flow) {
      if(condition()) task();
      else break;
    }
  }
}

这样拓展性应该会好一些,每个判断也能独立

let is_True = true;
let is_False = false;
const cbA = () => console.log("cbA");
const cbB = () => console.log("cbB");
const cbC = () => console.log("cbC");
const cbD = () => console.log("cbD");
function runTask() {
  const validationSet = {
    A: () => true,
    B: { precondition: "A", selfCheck: () => true },
    C: is_True,
    D: { precondition: "C", selfCheck: is_False },
  };
  const isConditionMet = (type) => {
    const validator = validationSet[type];

    function notObject(validator) {
      if (typeof validator === "function") return validator();
      if (typeof validator === "boolean") return validator;
      throw new Error("无效validator", validator);
    }

    if (typeof validator === "object") {
      const { precondition, selfCheck } = validator;
      if (!isConditionMet(precondition)) return false;
      return notObject(selfCheck);
    } else {
      return notObject(validator);
    }
  };

  const pendingFunctions = [
    ["A", cbA],
    ["B", cbB],
    ["C", cbC],
    ["D", cbD],
  ];
  pendingFunctions.forEach((item) => {
    const [validatorType, _function] = item;
    isConditionMet(validatorType) && _function();
  });
}
runTask();
function runTask() {
  if(条件A) cbA()
  if(条件A && 条件B) cbB()
  if(条件C) cbC()
  if(条件C && 条件D) cbD()
}

// 定义执行逻辑
const strategies = {
  callbackA: () => console.log('cbA'),
  callbackB: () => console.log('cbB'),
  callbackC: () => console.log('cbC'),
  callbackD: () => console.log('cbD'),
};

// 定义执行条件
const taskConfig = {
  A: true,
  B: true,
  C: true,
  D: true,
};

// 使用观察者模式执行命令,添加,执行
class CommandManager {
  constructor() {
    this.commands = [];
  }

  addCommand(command) {
    this.commands.push(command);
  }

  executeCommands() {
    this.commands.forEach((command) => command());
  }
}

// 执行
const runTask = () => {
  const commandManager = new CommandManager();

  if (taskConfig['A']) {
    commandManager.addCommand(strategies['callbackA']);
    if (taskConfig['B']) {
      commandManager.addCommand(strategies['callbackB']);
    }
  }

  if (taskConfig['C']) {
    commandManager.addCommand(strategies['callbackC']);
    if (taskConfig['D']) {
      commandManager.addCommand(strategies['callbackD']);
    }
  }

  commandManager.executeCommands();
};

runTask();

从题目看不出优化点,有可能是你脱敏的时候搞丢了。

老实说,从题目上完全看不出优化的方向。

上面几个答案我感觉有点为了【优化】而【优化】,在实际工作中,我宁可接手的代码是最开始的···

职责单一原则:首先,可以考虑将条件判断和任务执行分开,让代码更清晰易读。
策略模式:可以将每个条件和对应的回调函数封装成单独的对象或数据结构,比如一个对象数组,然后通过遍历这个数组并执行相应的操作来替代多重嵌套判断。
函数组合:如果条件和回调函数之间没有明确的依赖关系(即条件B不依赖于条件A的执行结果,条件D不依赖于条件C的执行结果),可以将所有条件和回调函数放入一个统一的管理结构中,然后使用函数式编程中的compose或者pipe函数进行优化。
下面是一种可能的优化方案:

// 定义任务对象,包含条件与回调函数
class Task {
  constructor(condition, callback) {
    this.condition = condition;
    this.callback = callback;
  }

  shouldRun() {
    return typeof this.condition === 'function' ? this.condition() : this.condition;
  }

  execute() {
    if (this.shouldRun()) {
      this.callback();
    }
  }
}

// 创建任务列表
const tasks = [
  new Task(条件A, () => { cbA(); }),
  new Task(条件B, () => { cbB(); }),
  new Task(条件C, () => { cbC(); }),
  new Task(条件D, () => { cbD(); }),
];

// 遍历任务列表执行
tasks.forEach(task => task.execute());

这样,当有新的条件和回调函数加入时,只需创建新的Task对象添加到tasks数组中即可,提高了代码的可维护性和扩展性。但需要注意的是,这种方式并不能处理条件间存在依赖关系的情况,对于这种情况,可能还需要根据实际逻辑调整优化方案。

这代码不就是好代码嘛 清晰简明 维护也好维护

新手上路,请多包涵

应该是考察的 IIFE 吧,改用立即执行函数优化.

首先条件AB、条件CD的判断相互独立,且逻辑是相同的,抽取重复逻辑,修改如下:

function runTaskForCondition(cond1, cond2, func1, func2) {
  if (cond1) {
    func1()
    if (cond2) {
      func2()
    }
  }
}
// 例如
function cb(tag) {
  console.log(tag);
} 
runTaskForCondition(条件A,条件B,() => cb('A'), () => cb('B'))
runTaskForCondition(条件C,条件D,() => cb('C'), () => cb('D'))

然后改为立即执行函,修改如下:

var runTask = (function(cond1, cond2, func1, func2) {
  if (cond1 && cond2) {
    return function() {
      func1()
      func2()
    }
  } else if (cond1) {
    return function() {
      func1()
    }
  } else {
    return function() {}
  }
})
// 例如
function cb(tag) {
  console.log(tag);
}
var taskAB = runTask(条件A, 条件B, () => cb('A'), () => cb('B'))
var taskCD = runTask(条件C, 条件D, () => cb('C'), () => cb('D'))
taskAB()
taskCD()

改用立即执行函数之后,各个条件判断只执行一次,后续调用 taskAB / taskCD 则会直接返回符合当前环境条件的函数,避免了重复的判断分支,节省了性能开销。

而源代码在调用时会依次进行4个分支判断,单独看没什么问题,但是具体的软件或者网站中,这些条件可能不会频繁变化,如果作为一个公用方法,或放入一个大数组循环执行,就会进行很多无用的判断分支,产生了额外的性能开销。

例如条件ABCD,AB是判断的服务器版本,v1执行A,v2执行AB,CD是判断的某SDK版本,sdk1执行C,sdk2执行CD,而这些条件在软件初始化时就已经确定,不需在重复判断。不知道我这么举例是否说清楚了。

但如果条件ABCD在软件运行周期中频繁变化,就不太适用于这个方案了,个人拙见仅供参考。

你说的优化应该是同步异步吧

function async runTask() {
  if(await 条件A){
    await cbA()
    if(await 条件B){
      cbB()
    }
  }
  if(await 条件C){
    await cbC()
    if(条件D){
      cbD()
    }
  }
}
新手上路,请多包涵

function runTask() {

if(条件A) cbA();
if(条件A && 条件B) cbB();
if(条件C) cbC();
if(条件C && 条件D) cbD();

}

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏