遇到一道设计模式的面试题,各位大佬看下如何解决,题目要求是优化这段业务代码
条件是布尔值或者函数返回值,cb 是函数
function runTask() {
if(条件A){
cbA()
if(条件B){
cbB()
}
}
if(条件C){
cbC()
if(条件D){
cbD()
}
}
}
遇到一道设计模式的面试题,各位大佬看下如何解决,题目要求是优化这段业务代码
条件是布尔值或者函数返回值,cb 是函数
function runTask() {
if(条件A){
cbA()
if(条件B){
cbB()
}
}
if(条件C){
cbC()
if(条件D){
cbD()
}
}
}
优化的方向有给吗?
我暂时想不出什么优化方案了,蹲一波。
这个方向是可读性:
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();
}
4 回答1.9k 阅读✓ 已解决
6 回答2k 阅读✓ 已解决
3 回答660 阅读✓ 已解决
7 回答4.3k 阅读✓ 已解决
5 回答680 阅读✓ 已解决
6 回答492 阅读✓ 已解决
7 回答1.3k 阅读