Patrones de diseño front-end y principios de diseño principios de diseño

Principios de diseño front-end

1 Principio de apertura y cierre

Este principio establece que las entidades de software (clases, módulos, funciones, etc.) deben estar abiertas a la extensión y cerradas a la modificación . En otras palabras, al agregar una nueva funcionalidad, se debe hacer extendiendo el código existente en lugar de modificarlo directamente. Esto garantiza la estabilidad del código existente y reduce el impacto en otras partes.

// 开闭原则示例

// 原始功能实现类
class OriginalFunctionality {
    
    
  performAction() {
    
    
    console.log("Original functionality");
  }
}

// 扩展功能实现类
class ExtendedFunctionality extends OriginalFunctionality {
    
    
  performAction() {
    
    
    super.performAction();
    console.log("Extended functionality");
  }
}

// 使用示例
const functionality = new ExtendedFunctionality();
functionality.performAction();

En el ejemplo anterior, hay una clase de implementación de función primitiva OriginalFunctionalityque define un performActionmétodo para realizar determinadas funciones.

De acuerdo con el principio abierto-cerrado, es necesario agregar nuevas funciones extendiendo en lugar de modificar la clase funcional original. Por lo tanto, cree una clase de implementación de función de extensión ExtendedFunctionalityque herede OriginalFunctionalityy anule performActionel método, llamando a la función original antes de ejecutar la nueva función.

Al aplicar el principio de apertura y cierre, se pueden reducir las modificaciones al código existente, mejorando así la estabilidad y la capacidad de mantenimiento del código. Al mismo tiempo, también hace que el código sea más fácil de ampliar y reutilizar, proporcionando un diseño de arquitectura más flexible.

Aquí se presenta otro ejemplo común del principio de apertura y cierre :

// 原始的 if-else 结构
function performAction(option) {
    
    
  if (option === 'A') {
    
    
    console.log("Performing action A");
  } else if (option === 'B') {
    
    
    console.log("Performing action B");
  } else if (option === 'C') {
    
    
    console.log("Performing action C");
  } else {
    
    
    console.log("Invalid option");
  }
}

// 使用 key-value 形式执行特定逻辑
const actions = {
    
    
  A: () => console.log("Performing action A"),
  B: () => console.log("Performing action B"),
  C: () => console.log("Performing action C"),
};

function performAction(option) {
    
    
  const action = actions[option];
  if (action) {
    
    
    action();
  } else {
    
    
    console.log("Invalid option");
  }
}

// 使用示例
performAction('A'); // 输出: Performing action A
performAction('B'); // 输出: Performing action B
performAction('C'); // 输出: Performing action C
performAction('D'); // 输出: Invalid option

Cambiar if-elseuna estructura key-valuea una forma para realizar una lógica específica puede verse como una forma de aplicar el principio de apertura y cierre. Dichos cambios permiten ampliar el código agregando nuevos pares clave-valor sin modificar la lógica original.

2 Principio de responsabilidad única

Este principio defiende que cada clase o módulo debe ser responsable de una sola función o tarea. Esto mejora la legibilidad, el mantenimiento y la reutilización del código. Cuando una clase tiene múltiples responsabilidades, se recomienda dividirla en varias clases independientes, cada una de las cuales se centra en una responsabilidad.

// 组件的单一职责示例

// 用户列表组件,负责渲染用户列表
class UserList {
    
    
  render(users) {
    
    
    // 渲染用户列表逻辑...
    console.log("User list rendered:", users);
  }
}

// 用户管理组件,负责处理用户的增删改操作
class UserManager {
    
    
  createUser(userData) {
    
    
    // 创建用户逻辑...
    console.log("User created:", userData);
  }

  updateUser(userId, userData) {
    
    
    // 更新用户逻辑...
    console.log("User updated:", userId, userData);
  }

  deleteUser(userId) {
    
    
    // 删除用户逻辑...
    console.log("User deleted:", userId);
  }
}

// 模块的单一职责示例

// 用户相关功能模块,仅负责用户相关的功能
const userModule = {
    
    
  createUser(userData) {
    
    
    // 创建用户逻辑...
    console.log("User created:", userData);
  },

  updateUser(userId, userData) {
    
    
    // 更新用户逻辑...
    console.log("User updated:", userId, userData);
  },

  deleteUser(userId) {
    
    
    // 删除用户逻辑...
    console.log("User deleted:", userId);
  }
};

// 函数的单一职责示例

// 检查用户名是否唯一
function checkUsernameUnique(username) {
    
    
  // 检查用户名唯一性逻辑...
  console.log("Checking username uniqueness:", username);
  return true;
}

// 验证密码
function validatePassword(password) {
    
    
  // 验证密码逻辑...
  console.log("Validating password:", password);
  return true;
}

// 使用示例
const userList = new UserList();
userList.render(["John", "Mike"]);

const userManager = new UserManager();
userManager.createUser({
    
     name: "John", age: 25 });

userModule.updateUser(1, {
    
     name: "Mike" });

checkUsernameUnique("john123");

validatePassword("password123");

Los ejemplos anteriores demuestran la aplicación del principio de responsabilidad única para componentes, módulos y funciones .

  • La responsabilidad única del componente: UserListel componente es responsable de representar la lista de usuarios y UserManagerel componente es responsable de procesar las operaciones de adición, eliminación y modificación del usuario. Cada componente sólo es responsable de una función específica, lo que hace que el código sea más claro y fácil de mantener.

  • La responsabilidad única del módulo: userModulees un módulo para funciones relacionadas con el usuario, que incluye las funciones de creación, actualización y eliminación de usuarios. Este módulo solo se centra en funciones relacionadas con el usuario, manteniendo la responsabilidad única del módulo.

  • La función tiene una única responsabilidad: checkUsernameUniquela función se usa para verificar si el nombre de usuario es único y validatePasswordla función se usa para verificar la contraseña. Cada función es responsable de una función específica, lo que hace que las responsabilidades de la función sean claramente visibles.

Al aplicar el principio de responsabilidad única, se pueden encapsular diferentes funciones en diferentes componentes, módulos y funciones, lo que hace que el código sea más legible, mantenible y reutilizable. Este enfoque de diseño nos ayuda a seguir el principio de responsabilidades independientes, mejorar la escalabilidad del código y reducir el acoplamiento innecesario.

3 Principio de inversión de dependencia

Este principio aboga por desacoplar las dependencias entre códigos mediante la abstracción. Los módulos de alto nivel deberían basarse en interfaces abstractas en lugar de detalles de implementación concretos. Esto reduce el acoplamiento entre módulos y hace que el sistema sea más fácil de ampliar y modificar, así como de probar.

// 不符合依赖倒置原则

class UserService {
    
    
  getUser(userId) {
    
    
    // 获取用户逻辑...
  }
}

class UserController {
    
    
  constructor() {
    
    
    this.userService = new UserService();
  }

  getUser(userId) {
    
    
    const user = this.userService.getUser(userId);
    // 处理用户数据逻辑...
  }
}

// 符合依赖倒置原则

class UserService {
    
    
  getUser(userId) {
    
    
    // 获取用户逻辑...
  }
}

class UserController {
    
    
  constructor(userService) {
    
    
    this.userService = userService;
  }

  getUser(userId) {
    
    
    const user = this.userService.getUser(userId);
    // 处理用户数据逻辑...
  }
}

// 使用示例

const userService = new UserService();
const userController = new UserController(userService);

userController.getUser(123);

El ejemplo anterior muestra una situación que no cumple con el principio de inversión de dependencia y una situación que sí cumple con el principio de inversión de dependencia.

En violación del principio, UserControllerse crea una instancia de directamente dentro de la clase UserService. Esta dependencia codificada conduce a un acoplamiento estrecho, que no favorece la expansión y el mantenimiento del código.

Al utilizar la inyección de dependencia, puede UserServicepasarla como parámetro al UserControllerconstructor de . De esta manera, UserControllerya no nos preocupamos por la UserServiceimplementación específica, sino que confiamos en la interfaz abstracta, lo que reduce el acoplamiento entre componentes.

Supongo que te gusta

Origin blog.csdn.net/weixin_45678402/article/details/132815339
Recomendado
Clasificación