不花里胡哨篇之前端设计模式与设计原则剖析

92 阅读17分钟

上周五面试官问我设计模式和设计原则,我没能答的很结构化,于是花了周末的时间梳理一下。虽然以前也做过比较口语化的相关的梳理

设计模式是一种经过验证的、可重复使用的解决方案,用于解决特定的设计问题。它们分为三大类:创建型模式、结构型模式和行为型模式。每一种模式都提供了一种独特的方法来解决特定类型的问题。

设计原则是指导设计模式中应用的基本准则。可以使你进行程序设计时遵循最佳实践,确保程序代码的可读性、可维护性和扩展性。

设计原则剖析

单一职责原则 (SRP)

每一个「代码块儿」负责的功能要单一。

有关设计模式

  1. 单例模式(Singleton)
  2. 工厂方法模式(Factory Method)
  3. 抽象工厂模式(Abstract Factory)
  4. 建造者模式(Builder)
  5. 原型模式(Prototype)
  6. 适配器模式(Adapter)
  7. 装饰器模式(Decorator)
  8. 代理模式(Proxy)
  9. 组合模式(Composite)
  10. 外观模式(Facade)
  11. 享元模式(Flyweight)
  12. 桥接模式(Bridge)
  13. 策略模式(Strategy)
  14. 模板方法模式(Template Method)
  15. 责任链模式(Chain of Responsibility)
  16. 中介者模式(Mediator)
  17. 观察者模式(Observer)
  18. 访问者模式(Visitor)
  19. 备忘录模式(Memento)
  20. 状态模式(State)
  21. 解释器模式(Interpreter)
  22. 迭代器模式(Iterator)
  23. 命令模式(Command)

开放封闭原则 (OCP)

一个健壮的程序,它的扩展性会很不错,所以要对扩展开放。 一个优秀的程序,它的代码不应改来改去,所以要对修改封闭。

有关设计模式

  1. 工厂方法模式(Factory Method)
  2. 抽象工厂模式(Abstract Factory)
  3. 建造者模式(Builder)
  4. 原型模式(Prototype)
  5. 适配器模式(Adapter)
  6. 装饰器模式(Decorator)
  7. 组合模式(Composite)
  8. 外观模式(Facade)
  9. 享元模式(Flyweight)
  10. 桥接模式(Bridge)
  11. 策略模式(Strategy)
  12. 模板方法模式(Template Method)
  13. 责任链模式(Chain of Responsibility)
  14. 观察者模式(Observer)
  15. 访问者模式(Visitor)
  16. 状态模式(State)
  17. 解释器模式(Interpreter)
  18. 命令模式(Command)

里氏替换原则 (LSP)

你实现的子程序可以替换父程序来进行扩展或切换全新的功能实现。

有关设计模式

  1. 工厂方法模式(Factory Method)
  2. 抽象工厂模式(Abstract Factory)
  3. 建造者模式(Builder)
  4. 原型模式(Prototype)
  5. 装饰器模式(Decorator)
  6. 组合模式(Composite)
  7. 享元模式(Flyweight)
  8. 桥接模式(Bridge)
  9. 策略模式(Strategy)
  10. 模板方法模式(Template Method)
  11. 访问者模式(Visitor)
  12. 状态模式(State)

接口隔离原则 (ISP)

功能的设计,要根据具体场景进行划分,粒度要细一些,这样就可以像拼乐高积木一样,自由拼合。

有关设计模式

  1. 工厂方法模式(Factory Method)
  2. 抽象工厂模式(Abstract Factory)
  3. 建造者模式(Builder)
  4. 策略模式(Strategy)

依赖倒置原则 (DIP)

面对复杂,先抽象、后具体。在设计阶段,具体细节的实现方式比较多变,而抽象相对来说较稳定。

有关设计模式

  1. 工厂方法模式(Factory Method)
  2. 抽象工厂模式(Abstract Factory)
  3. 建造者模式(Builder)
  4. 装饰器模式(Decorator)
  5. 桥接模式(Bridge)
  6. 代理模式(Proxy)
  7. 中介者模式(Mediator)
  8. 观察者模式(Observer)
  9. 访问者模式(Visitor)
  10. 备忘录模式(Memento)
  11. 状态模式(State)
  12. 命令模式(Command)

迪米法则 (LOD) (最少知道原则)

强调功能的划分,从而减少功能与功能之间的耦合。减少模块之间的耦合,提高模块之间的独立性。

有关设计模式

  1. 适配器模式(Adapter)
  2. 外观模式(Facade)
  3. 中介者模式(Mediator)

组合聚合复用原则 (CRP)

组合和聚合的方式相对继承而言,它们要灵活很多,想用什么就借用相应对象的功能即可,不需要关注该对象中不需要的功能。

有关设计模式

  1. 抽象工厂模式(Abstract Factory)
  2. 建造者模式(Builder)
  3. 原型模式(Prototype)
  4. 组合模式(Composite)
  5. 装饰器模式(Decorator)
  6. 桥接模式(Bridge)

不重复你自己 (DRY)

注重设计,重复代码写的越多改的也会越多,功能语义相同和代码逻辑重复的代码该合并封装的合并封装、该删除抽象的删除抽象。

有关设计模式

  1. 单例模式(Singleton)
  2. 原型模式(Prototype)
  3. 享元模式(Flyweight)
  4. 桥接模式(Bridge)
  5. 模板方法模式(Template Method)
  6. 代理模式(Proxy)

尽量保持简单 (KISS)

做项目要考虑后续的可维护性,代码可读性好,是能够提升开发效率和提高可维护性的。 尽可能使用简单可读性高的方式去书写代码,不应该用逻辑重复、逻辑复杂、较偏门、可读性差的方式编写代码。「与防御型编程的设计原则完全相反」🐶

有关设计模式

  1. 单例模式(Singleton)
  2. 适配器模式(Adapter)
  3. 装饰器模式(Decorator)
  4. 桥接模式(Bridge)
  5. 代理模式(Proxy)
  6. 外观模式(Facade)
  7. 策略模式(Strategy)
  8. 责任链模式(Chain of Responsibility)
  9. 中介者模式(Mediator)
  10. 观察者模式(Observer)
  11. 迭代器模式(Iterator)
  12. 命令模式(Command)

不过度设计 (YAGNI)

过度设计会增加一个程序的理解成本,如果这部分理解成本根本没必要,那么这样的设计就是浪费时间。

有关设计模式

  1. 工厂方法模式(Factory Method)
  2. 装饰器模式(Decorator)
  3. 策略模式(Strategy)
  4. 模板方法模式(Template Method)
  5. 责任链模式(Chain of Responsibility)
  6. 代理模式(Proxy)
  7. 组合模式(Composite)

设计模式剖析

创建型模式:对象的创建和使用解耦了,灵活和多样的去创建对象,使得代码更加模块化和可扩展。

结构型模式:总结出了类、对象组合后的经典结构,将类、对象的结构和使用解耦了,简化代码的维护和扩展,灵活的借用对象,使它们的结构更加灵活和可扩展。

行为型模式:总结出了 类、对象之间的经典交互和职责分配方式,将类、对象的行为和使用解耦了,灵活的去使用对象的行为来完成特定场景下的功能,便于代码的维护和扩展。

1. 单例模式(Singleton)

示例:全局状态管理,如Redux Store的实例化。

class Store {
  constructor() {
    if (!Store.instance) {
      this.state = {};
      Store.instance = this;
    }
    return Store.instance;
  }
}
const store = new Store();

有关设计原则

  • 单一职责原则 (SRP):只负责提供唯一实例。
  • 不重复你自己 (DRY):确保全局唯一实例,避免重复创建。
  • 尽量保持简单 (KISS):实现简单易懂,确保唯一实例。

2. 工厂方法模式(Factory Method)

示例:根据不同参数创建不同类型的组件实例。

class ButtonFactory {
  createButton(type) {
    if (type === 'Primary') return new PrimaryButton();
    if (type === 'Secondary') return new SecondaryButton();
  }
}

有关设计原则

  • 开放封闭原则 (OCP):可以通过扩展来添加新类型按钮。
  • 依赖倒置原则 (DIP):依赖于抽象而不是具体类。
  • 不过度设计 (YAGNI):只实现当前需要的按钮类型,避免过度设计。

3. 抽象工厂模式(Abstract Factory)

**示例 1 **:创建一组相关或依赖的对象,如创建一整套表单控件。

class FormControlFactory {
  createTextInput() {
    return new TextInput();
  }
  createCheckbox() {
    return new Checkbox();
  }
}

**示例 2 **:为不同平台(如 Web 和 Mobile)创建 UI 组件。

class WebUIFactory {
  createButton() {
    return new WebButton();
  }
  createModal() {
    return new WebModal();
  }
}

有关设计原则

  • 开放封闭原则 (OCP):可以通过扩展来添加新控件。
  • 单一职责原则 (SRP):每个工厂类负责创建一组相关对象。
  • 依赖倒置原则 (DIP):依赖于抽象接口而不是具体实现。

4. 建造者模式(Builder)

示例:逐步构建复杂的表单组件。

class FormBuilder {
  constructor() {
    this.form = new Form();
  }
  addTextInput(name) {
    this.form.addInput(new TextInput(name));
    return this;
  }
  addCheckbox(name) {
    this.form.addInput(new Checkbox(name));
    return this;
  }
  build() {
    return this.form;
  }
}
const form = new FormBuilder().addField('username', 'text').addField('password', 'password').build();

有关设计原则

  • 单一职责原则 (SRP):建造者类负责构建复杂对象。
  • 开放封闭原则 (OCP):可以通过扩展建造者类来添加新组件。
  • 组合聚合复用原则 (CRP):通过组合方式构建复杂对象。

5. 原型模式(Prototype)

示例:通过克隆已有对象来创建新对象,避免重复初始化。

const buttonPrototype = {
  type: 'Default',
  clone() {
    return Object.assign({}, this);
  }
};
const primaryButton = buttonPrototype.clone();
primaryButton.type = 'Primary';

有关设计原则

  • 单一职责原则 (SRP):原型类负责克隆自己。
  • 不重复你自己 (DRY):通过克隆避免重复创建相同对象。
  • 尽量保持简单 (KISS):克隆逻辑简单易懂。

6. 适配器模式(Adapter)

示例:适配不同API的数据格式,使其符合应用程序的数据接口。

class APIAdapter {
  constructor(api) {
    this.api = api;
  }
  getData() {
    const rawData = this.api.fetchData();
    return this.transformData(rawData);
  }
  transformData(data) {
    // 转换数据格式
  }
}

有关设计原则

  • 单一职责原则 (SRP):适配器类只负责数据转换。
  • 不重复你自己 (DRY):数据转换逻辑集中在适配器中。
  • 尽量保持简单 (KISS):转换逻辑简单易懂。

7. 装饰器模式(Decorator)

示例:为组件添加额外的功能,如在按钮上添加日志记录功能。

function logButtonClick(Component) {
  return function WrappedComponent(props) {
    const handleClick = () => {
      console.log('Button clicked');
      props.onClick();
    };
    return <Component {...props} onClick={handleClick} />;
  };
}

有关设计原则

  • 开放封闭原则 (OCP):可以通过添加新装饰器扩展功能。
  • 单一职责原则 (SRP):每个装饰器负责单一功能。
  • 不过度设计 (YAGNI):只添加当前需要的装饰器。

8. 代理模式(Proxy)

示例:在数据请求前进行缓存或权限检查。

class APIProxy {
  constructor(api) {
    this.api = api;
    this.cache = {};
  }
  fetchData(endpoint) {
    if (!this.cache[endpoint]) {
      this.cache[endpoint] = this.api.fetchData(endpoint);
    }
    return this.cache[endpoint];
  }
}

有关设计原则

  • 单一职责原则 (SRP):代理类只负责缓存和权限检查。
  • 不重复你自己 (DRY):缓存逻辑集中在代理类中。
  • 尽量保持简单 (KISS):代理逻辑简单易懂。

9. 组合模式(Composite)

示例:处理树形结构的组件,如文件系统或菜单。

class MenuItem {
  constructor(name) {
    this.name = name;
    this.children = [];
  }
  add(child) {
    this.children.push(child);
  }
  display() {
    console.log(this.name);
    this.children.forEach(child => child.display());
  }
}

有关设计原则

  • 组合聚合复用原则 (CRP):通过组合方式构建树形结构。
  • 单一职责原则 (SRP):每个菜单项负责自己的显示和管理。
  • 开放封闭原则 (OCP):可以通过扩展添加新类型的菜单项。

10. 外观模式(Facade)

示例 1:简化复杂的API调用,如简化DOM操作。

class DOMFacade {
  static createElement(type, attributes) {
    const element = document.createElement(type);
    for (let key in attributes) {
      element.setAttribute(key, attributes[key]);
    }
    return element;
  }
}

示例 2:为复杂的操作提供简单的接口,如封装多个 API 调用。

class APIClient {
  constructor() {
    this.userAPI = new UserAPI();
    this.orderAPI = new OrderAPI();
  }
  getUserOrder(userId) {
    const user = this.userAPI.getUser(userId);
    const orders = this.orderAPI.getOrders(userId);
    return { user, orders };
  }
}

有关设计原则

  • 单一职责原则 (SRP):外观类只负责简化接口。
  • 尽量保持简单 (KISS):提供简单易用的接口。
  • 不重复你自己 (DRY):统一复杂操作,避免重复代码。

11. 享元模式(Flyweight)

示例:在大批量创建对象时共享相同部分的数据,如图形绘制中的共享样式。

class Shape {
  constructor(type) {
    this.type = type;
  }
}
const shapeFactory = (function() {
  const shapes = {};
  return {
    getShape(type) {
      if (!shapes[type]) {
        shapes[type] = new Shape(type);
      }
      return shapes[type];
    }
  };
})();

示例:共享相同的数据对象,减少内存开销,如在表格中共享相同的样式对象。

class StyleFlyweight {
constructor() {
  this.styles = {};
}
getStyle(style) {
  if (!this.styles[style]) {
    this.styles[style] = new Style(style);
  }
  return this.styles[style];
}
}

有关设计原则

  • 单一职责原则 (SRP):享元类负责共享对象。
  • 不重复你自己 (DRY):通过共享避免重复创建相同对象。
  • 尽量保持简单 (KISS):共享逻辑简单易懂。

12. 桥接模式(Bridge)

示例:在前端开发中使用桥接模式来分离视图与渲染逻辑,使得可以在不同的环境下使用不同的渲染方法。

// 渲染器接口
class Renderer {
  render(content) {
    throw new Error('Render method must be implemented');
  }
}

// HTML 渲染器
class HTMLRenderer extends Renderer {
  render(content) {
    console.log(`<div>${content}</div>`);
  }
}

// Markdown 渲染器
class MarkdownRenderer extends Renderer {
  render(content) {
    console.log(`**${content}**`);
  }
}

// 抽象的视图
class View {
  constructor(renderer) {
    this.renderer = renderer;
  }
  display(content) {
    this.renderer.render(content);
  }
}

// 具体的视图实现
class ArticleView extends View {
  display(content) {
    console.log('Article View:');
    super.display(content);
  }
}

// 使用 HTML 渲染器
const htmlRenderer = new HTMLRenderer();
const articleViewWithHTML = new ArticleView(htmlRenderer);
articleViewWithHTML.display('Hello World');

// 使用 Markdown 渲染器
const markdownRenderer = new MarkdownRenderer();
const articleViewWithMarkdown = new ArticleView(markdownRenderer);
articleViewWithMarkdown.display('Hello World');

有关设计原则

  • 开放封闭原则 (OCP):可以通过添加新的渲染器扩展视图的渲染方式,而不修改现有代码。
  • 单一职责原则 (SRP):视图类负责内容的显示逻辑,渲染器类负责具体的渲染实现。
  • 依赖倒置原则 (DIP):视图类依赖于抽象的渲染器接口,而不是具体的渲染器实现。

13. 策略模式(Strategy)

示例:在表单验证中使用不同的验证策略。

class Validator {
  constructor(strategy) {
    this.strategy = strategy;
  }
  validate(value) {
    return this.strategy(value);
  }
}
const emailStrategy = (value) => /\S+@\S+\.\S+/.test(value);
const emailValidator = new Validator(emailStrategy);

有关设计原则

  • 开放封闭原则 (OCP):可以通过添加新策略扩展验证逻辑。
  • 单一职责原则 (SRP):每个策略负责单一验证逻辑。
  • 不过度设计 (YAGNI):只实现当前需要的验证策略。

14. 模板方法模式(Template Method)

示例 1:定义算法的骨架并将一些步骤延迟到子类实现,如表单提交处理。

class FormHandler {
  submit() {
    this.validate();
    this.send();
    this.confirm();
  }
  validate() {
    // 子类实现
  }
  send() {
    // 子类实现
  }
  confirm() {
    // 子类实现
  }
}

示例 2:在组件渲染中定义骨架流程,子组件实现具体细节。

class BaseComponent {
    render() {
      this.renderHeader();
      this.renderBody();
      this.renderFooter();
    }
    renderHeader() {
      throw new Error('You have to implement the method renderHeader!');
    }
    renderBody() {
      throw new Error('You have to implement the method renderBody!');
    }
    renderFooter() {
      throw new Error('You have to implement the method renderFooter!');
    }
}

class CustomComponent extends BaseComponent {
    renderHeader() {
      console.log('Rendering custom header');
    }
    renderBody() {
      console.log('Rendering custom body');
    }
    renderFooter() {
      console.log('Rendering custom footer');
    }
}

有关设计原则

  • 单一职责原则 (SRP) :模板方法类负责算法骨架,具体实现由子类负责。
  • 里氏替换原则 (LSP) :子类可以替换父类,实现其行为而不改变算法的整体结构。
  • 不重复你自己 (DRY) :将通用的算法骨架定义在父类中,避免在子类中重复编写相同的逻辑。
  • 开放封闭原则 (OCP) :可以通过扩展子类来添加新的行为,而无需修改已有的代码。

15. 责任链模式(Chain of Responsibility)

示例 1:事件处理链,如React中的事件传播机制。

class EventHandler {
  setNext(handler) {
    this.nextHandler = handler;
    return handler;
  }
  handle(event) {
    if (this.nextHandler) {
      this.nextHandler.handle(event);
    }
  }
}

示例 2:在表单验证中设置多个验证步骤,逐个执行。

 class Validator {
   setNext(validator) {
     this.nextValidator = validator;
     return validator;
   }
   validate(request) {
     if (this.nextValidator) {
       return this.nextValidator.validate(request);
     }
     return true;
   }
 }
 class EmailValidator extends Validator {
   validate(request) {
     if (!/\S+@\S+\.\S+/.test(request.email)) {
       return false;
     }
     return super.validate(request);
   }
 }
 class PasswordValidator extends Validator {
   validate(request) {
     if (request.password.length < 6) {
       return false;
     }
     return super.validate(request);
   }
 }
 const emailValidator = new EmailValidator();
 const passwordValidator = new PasswordValidator();
 emailValidator.setNext(passwordValidator);
 const isValid = emailValidator.validate({ email: 'test@example.com', password: 'password123' });

有关设计原则

  • 单一职责原则 (SRP):每个处理器验证器负责处理自己的事件。
  • 开闭原则 (OCP):可以通过添加新处理器验证器扩展事件处理链。
  • 尽量保持简单 (KISS):处理链逻辑简单易懂。

16. 观察者模式(Observer)

示例:数据变化通知,如React的状态管理。

class Observable {
  constructor() {
    this.observers = [];
  }
  subscribe(observer) {
    this.observers.push(observer);
  }
  notify(data) {
    this.observers.forEach(observer => observer.update(data));
  }
}

有关设计原则

  • 单一职责原则 (SRP):被观察者负责通知变化。
  • 开闭原则 (OCP):可以通过添加新观察者扩展通知逻辑。
  • 尽量保持简单 (KISS):通知逻辑简单易懂。

17. 访问者模式(Visitor)

示例:操作复杂数据结构,如在 DOM 树上执行操作。

// 访问者接口
class Visitor {
  visit(element) {
    if (element instanceof DivElement) {
      this.visitDiv(element);
    } else if (element instanceof SpanElement) {
      this.visitSpan(element);
    }
  }

  visitDiv(element) {
    // 处理 Div 元素
    console.log(`Visiting Div: ${element.id}`);
  }

  visitSpan(element) {
    // 处理 Span 元素
    console.log(`Visiting Span: ${element.id}`);
  }
}

// 元素接口
class Element {
  accept(visitor) {
    throw new Error('accept method must be implemented');
  }
}

// 具体元素
class DivElement extends Element {
  constructor(id) {
    super();
    this.id = id;
  }

  accept(visitor) {
    visitor.visitDiv(this);
  }
}

class SpanElement extends Element {
  constructor(id) {
    super();
    this.id = id;
  }

  accept(visitor) {
    visitor.visitSpan(this);
  }
}

// 使用访问者模式
const elements = [new DivElement('div1'), new SpanElement('span1')];
const visitor = new Visitor();

elements.forEach(element => {
  element.accept(visitor);
});

有关设计原则

  • 单一职责原则 (SRP):访问者类负责执行操作,将操作逻辑与数据结构分离。
  • 开闭原则 (OCP):可以通过添加新访问者来扩展操作,而不修改现有的元素类。
  • 里氏替换原则 (LSP):不同元素可以被相同操作访问,元素类的行为一致。
  • 依赖倒置原则 (DIP):高层模块(操作逻辑)不应该依赖低层模块(具体元素实现),它们都应该依赖抽象(访问者接口和元素接口)。

18. 备忘录模式(Memento)

示例:保存和恢复对象的状态,如表单的撤销操作。

class Form {
  constructor() {
    this.state = {};
  }
  save() {
    return { ...this.state };
  }
  restore(state) {
    this.state = state;
  }
}

有关设计原则

  • 单一职责原则 (SRP):备忘录类负责保存和恢复状态。
  • 依赖倒置原则 (DIP):依赖于备忘录接口而不是具体实现。
  • 不重复你自己 (DRY):通过备忘录避免重复实现保存和恢复逻辑。

19. 状态模式(State)

示例:根据状态变化执行不同的行为,如表单的验证状态。

class Form {
  constructor() {
    this.state = new InitialState(this);
  }
  setState(state) {
    this.state = state;
  }
  submit() {
    this.state.submit();
  }
}
class InitialState {
  constructor(form) {
    this.form = form;
  }
  submit() {
    // 初始状态下的提交逻辑
  }
}
class ValidatedState {
  constructor(form) {
    this.form = form;
  }
  submit() {
    // 验证通过后的提交逻辑
  }
}

有关设计原则

  • 单一职责原则 (SRP):每个状态类负责处理自己的行为。
  • 里氏替换原则 (LSP):不同状态可以替换彼此,确保行为一致。
  • 尽量保持简单 (KISS):状态转换逻辑简单易懂。

20. 解释器模式(Interpreter)

示例:解析和执行DSL(领域特定语言),如模板引擎。

class Interpreter {
  interpret(context) {
    const expressions = context.split(' ');
    expressions.forEach(expression => {
      // 解析并执行表达式
    });
  }
}

有关设计原则

  • 单一职责原则 (SRP):解释器类负责解析和执行表达式。
  • 开闭原则 (OCP):可以通过扩展解析新表达式。
  • 尽量保持简单 (KISS):解析逻辑简单易懂。

21. 迭代器模式(Iterator)

示例:遍历集合,如遍历DOM节点或数组。

class Iterator {
  constructor(collection) {
    this.collection = collection;
    this.index = 0;
  }
  next() {
    return this.collection[this.index++];
  }
  hasNext() {
    return this.index < this.collection.length;
  }
}

有关设计原则

  • 单一职责原则 (SRP):迭代器类负责遍历集合。
  • 开闭原则 (OCP):可以通过扩展支持新集合类型。
  • 尽量保持简单 (KISS):遍历逻辑简单易懂。

22. 命令模式(Command)

示例:将请求封装为对象,如按钮点击事件的处理。

class Command {
  execute() {
    // 执行命令
  }
}
class ClickCommand extends Command {
  execute() {
    console.log('Button clicked');
  }
}

有关设计原则

  • 单一职责原则 (SRP):命令类负责封装请求。
  • 开闭原则 (OCP):可以通过扩展添加新命令。
  • 依赖倒置原则 (DIP):依赖于命令接口而不是具体实现。

23. 中介者模式(Mediator)

示例:组件间通信的中心,如Redux中的store。

class EventBus {
  constructor() {
    this.listeners = {};
  }
  subscribe(event, listener) {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(listener);
  }
  publish(event, data) {
    if (this.listeners[event]) {
      this.listeners[event].forEach(listener => listener(data));
    }
  }
}

有关设计原则

  • 单一职责原则 (SRP):中介者类负责协调对象之间的通信。
  • 迪米特法则 (LOD):通过中介者减少对象间的直接依赖。
  • 依赖倒置原则 (DIP):依赖于中介者接口而不是具体实现。

通过设计模式和设计原则可以创建高效、可维护和扩展性强的前端应用。在前端开发中也提供了许多有价值的方法来组织和管理代码。应用这些模式和原则,理解这些模式的基本原理和适用场景,才能在实际开发中灵活运用,最终可以显著提升代码质量和开发效率。