What is the strategy pattern
Definition of Strategy mode: This mode defines a series of algorithms and encapsulates each algorithm so that they can be replaced with each other, and the change of the algorithm will not affect the customers who use the algorithm.
problem to be solved
Suppose we need to write a function to calculate the year-end bonus, our code may look like this
const bonus = function (level, salary) {
if (level === "S") {
return salary * 1.1;
}
if (level === "A") {
return salary * 1;
}
if (level === "B") {
return salary * 0.9;
}
};
There are some problems with writing code like this:
- If there are many situations, there will be a lot of judgment logic, and the code will be messy
- Violates the design principle of closed development (open to expansion, closed to modification), adding logic must modify the original function
We can optimize with the help of strategy pattern.
Single Responsibility Transformation
The return statement in each condition of the above code is an algorithm , and we can encapsulate each algorithm into a function
const levelS = (salary) => {
return salary * 1.1;
};
const levelA = (salary) => {
return salary * 1;
};
const levelB = (salary) => {
return salary * 0.9;
};
const bonus = function (level, salary) {
if (level === "S") {
return levelS(salary);
}
if (level === "A") {
return levelA(salary);
}
if (level === "B") {
return levelB(salary);
}
};
After encapsulating in this way, the algorithm for calculating the bonus in each game is separated separately for easy maintenance. But if there are other situations, we still need to write an if statement to the bonus function, and we need to continue to optimize
Development closed transformation
const levelObj = {
S: (salary) => {
return salary * 1.1;
},
A: (salary) => {
return salary * 1;
},
B: (salary) => {
return salary * 0.9;
},
};
const bonus = function (level, salary) {
return levelObj[level](salary);
};
After this modification, if there is still D, we can modify it like this
levelObj.D = (salary)=> {
return salary * 0.8;
},
It can be seen that the strategy mode can better solve the loop nesting of the if statement.
No matter how the logic in each of the above algorithms S, A, B, and D changes, it will not affect the core logic of the bonus. Therefore, we say that the strategy pattern defines a series they They can be replaced with each other, and changes in the algorithm will not affect customers who use the algorithm.
Use in vite configuration
Suppose our vite has three configuration files, a common viteBaseConfig configuration, a dev mode viteDevConfig configuration, and a production mode viteProdConfig configuration.
import { defineConfig } from "vite";
import viteBaseConfig from "./vite.base.config";
import viteDevConfig from "./vite.dev.config";
import viteProdConfig from "./vite.prod.config";
export default defineConfig(({ command, mode, ssrBuild }) => {
if (command === "serve") {
return {
// dev 独有配置
...viteBaseConfig,
...viteProdConfig
};
} else {
// command === 'build'
return {
// build 独有配置
...viteBaseConfig,
...viteDevConfig
};
}
});
For details, please refer to this article: https://juejin.cn/post/7172009616967942175
The above code uses the if statement to return different configuration items according to different modes, and we optimize it according to the knowledge we just learned.
Single Responsibility Transformation
//....
export default defineConfig(({ command, mode, ssrBuild }) => {
const build = () => {
// Object.assign中的{}是为了防止viteBaseConfig被修改。
Object.assign({}, viteBaseConfig, viteProdConfig)
},
const serve = () => {
// Object.assign中的{}是为了防止viteBaseConfig被修改。
Object.assign({}, viteBaseConfig, viteDevConfig)
},
if (command === "serve") {
return build()
} else {
// command === 'build'
return serve();
}
});
Object.assign() The Object.assign() method copies all enumerable properties from one or more source objects to a target object, returning the modified object. Note: This method modifies the source object!
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget === target);
// expected output: true
Development closed transformation
const envResolver = {
build: () => Object.assign({}, viteBaseConfig, viteProdConfig),
serve: () => Object.assign({}, viteBaseConfig, viteDevConfig),
};
export default defineConfig(({ command, mode, ssrBuild }) => {
return envResolver[command]();
});