Front-end Design Patterns - Strategy Patterns

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]();
});

Guess you like

Origin blog.csdn.net/weixin_46769087/article/details/131406594