前端常用设计模式

这篇具有很好参考价值的文章主要介绍了前端常用设计模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

SOLID设计原则

// 单一职责原则(Single Responsibility Principle,SRP)

// 负责显示用户信息的组件
class UserInfoComponent {
  render(user) {
    // 渲染用户信息到DOM
  }

  // 发送请求获取用户信息
  fetchUserInfo(userId) {
    // 发送Ajax请求获取用户信息
  }
}

在上述案例中,UserInfoComponent负责两个职责:显示用户信息和发送请求获取用户信息。如果我们将发送请求的逻辑提取到一个单独的服务或钩子函数中,可以更好地遵守单一职责原则。

// 单一职责原则(Single Responsibility Principle,SRP)

// 负责显示用户信息的组件
class UserInfoComponent {
  render(user) {
    // 渲染用户信息到DOM
  }
}

// 用户信息服务
class UserInfoService {
  fetchUserInfo(userId) {
    // 发送Ajax请求获取用户信息
  }
}
// 开放封闭原则(Open-Closed Principle,OCP)

// 主题切换功能
class ThemeSwitcher {
  constructor() {
    this.currentTheme = 'default';
  }

  // 切换主题
  switchTheme(theme) {
    // 切换应用的外观样式
  }
}

在上述案例中,主题切换功能违反了开放封闭原则,因为每次添加新的主题都需要修改切换主题的方法。更好的做法是通过使用CSS预处理器或主题配置文件来实现主题切换,而无需修改原有的代码。

// 开放封闭原则(Open-Closed Principle,OCP)

// 主题切换功能
class ThemeSwitcher {
  constructor() {
    this.currentTheme = 'default';
  }

  // 切换主题
  switchTheme(theme) {
    // 切换应用的外观样式
  }

  // 添加新的主题
  addTheme(theme) {
    // 添加新的主题文件或修改配置
  }
}
// 里氏替换原则(Liskov Substitution Principle,LSP)

// 基础页面组件
class BasePageComponent {
  render() {
    // 渲染页面
  }

  // 处理页面逻辑
  handlePageLogic() {
    // 处理页面逻辑
  }
}

// 子页面组件
class SubPageComponent extends BasePageComponent {
  render() {
    // 渲染子页面
  }

  // 重写父类的页面逻辑处理方法
  handlePageLogic() {
    // 处理子页面特定的逻辑
  }
}

在上述案例中,子页面组件继承自基础页面组件,并重写了页面逻辑处理方法。确保子组件可以无缝替换基础组件,而不会影响程序的正确性。

// 接口隔离原则(Interface Segregation Principle,ISP)

// 实用函数模块
const UtilityFunctions = {
  // 生成随机字符串
  generateRandomString() {
    // 生成随机字符串的逻辑
  },

  // 加密字符串
  encryptString(str) {
    // 加密字符串的逻辑
  }
};

在上述案例中,将实用函数拆分为独立的模块,每个模块只包含相关的函数,以便开发者可以选择性地引入和使用。

// 依赖倒置原则(Dependency Inversion Principle,DIP)

// 数据服务接口
class DataService {
  fetchData() {
    // 获取数据的逻辑
  }
}

// 前端组件
class MyComponent {
  constructor(dataService) {
    this.dataService = dataService;
  }

  fetchData() {
    this.dataService.fetchData();
  }
}

// 创建具体的数据服务实例
const dataService = new DataService();

// 创建前端组件实例并注入数据服务
const myComponent = new MyComponent(dataService);

在上述案例中,前端组件通过依赖注入方式接收一个数据服务的实例。这样,组件不直接依赖于具体的数据服务类,而是依赖于抽象的接口,从而减少了组件与具体实现的耦合,提高了代码的灵活性和可测试性。

单例模式

单例模式是一种设计模式,它确保一个类只有一个实例,并提供全局访问点。在前端开发中,单例模式常用于管理全局状态、资源共享和避免重复创建对象等场景。以下是一个前端的单例模式代码案例,附带注释说明:

// 前端单例模式案例

// 单例对象
class Singleton {
  constructor() {
    // 初始化操作
    // ...
  }

  // 单例方法
  someMethod() {
    // 方法逻辑
  }
}

// 单例实例
const singletonInstance = new Singleton();

// 全局访问点
const SingletonInstance = {
  getInstance() {
    return singletonInstance;
  }
};

// 使用单例对象
const instance = SingletonInstance.getInstance();
instance.someMethod();

在上述案例中,我们定义了一个Singleton类作为单例对象的实现。该类在构造函数中执行初始化操作,你可以根据具体需求进行扩展。
通过将单例对象的实例存储在全局访问点SingletonInstance中,我们可以在应用程序的任何地方获取该单例实例。
在使用单例对象时,我们首先通过SingletonInstance.getInstance() 获取单例实例,然后调用其方法进行操作。由于单例模式保证了只有一个实例存在,所以我们可以在不同的模块或组件中共享相同的实例。
需要注意的是,单例模式虽然可以方便地共享实例,但也可能带来全局状态管理的问题。使用时应慎重考虑,确保单例对象的使用符合设计需求,并避免滥用导致代码的可测试性和可维护性下降。

原型模式

原型模式是一种设计模式,它通过复制现有对象的原型来创建新的对象。在前端开发中,原型模式常用于创建可复制的对象,以减少重复创建和初始化的开销。以下是一个前端的原型模式代码案例,附带注释说明:

// 前端原型模式案例

// 原型对象
class Prototype {
  constructor() {
    // 属性初始化
    // ...
  }

  // 克隆方法
  clone() {
    return Object.create(Object.getPrototypeOf(this));
  }
}

// 创建原型对象实例
const prototypeInstance = new Prototype();

// 克隆对象
const clonedInstance = prototypeInstance.clone();

// 使用克隆的对象
clonedInstance.someMethod();

在上述案例中,我们定义了一个Prototype类作为原型对象的实现。该类具有一些属性和方法,可以根据具体需求进行扩展。
通过调用clone() 方法,我们可以使用现有的原型对象创建一个新的对象。在该方法中,我们使用Object.create() 来克隆原型对象,它会创建一个新对象,并将原型对象设置为该新对象的原型。
通过克隆对象,我们可以在不重新初始化属性的情况下创建新的对象,以减少重复创建和初始化的开销。
需要注意的是,克隆的对象是浅拷贝的,即它们共享相同的原型。如果在克隆后的对象中修改了某些属性,将会影响到原型对象和其他克隆对象。如果需要深拷贝对象,可以根据具体情况使用工具库或手动实现深拷贝逻辑。
原型模式可以在前端开发中用于创建可复制的对象,例如在原型对象上定义一些通用的方法或属性,然后通过克隆来创建具有相同行为的新对象。这样可以节省资源和提高性能,特别适用于创建大量相似对象的情况。

代理模式

代理模式是一种设计模式,它通过引入代理对象来控制对实际对象的访问。在前端开发中,代理模式常用于实现缓存、权限控制、延迟加载等功能。以下是一个前端的代理模式代码案例,附带注释说明:

// 前端代理模式案例

// 实际对象
class RealObject {
  // 一些操作和方法
  someMethod() {
    // 方法逻辑
  }
}

// 代理对象
class ProxyObject {
  constructor() {
    this.realObject = new RealObject();
  }

  // 代理方法
  someMethod() {
    // 在调用实际对象方法之前可以执行一些前置操作
    // ...

    // 调用实际对象的方法
    this.realObject.someMethod();

    // 在调用实际对象方法之后可以执行一些后置操作
    // ...
  }
}

// 使用代理对象
const proxy = new ProxyObject();
proxy.someMethod();

在上述案例中,我们有一个实际对象RealObject和一个代理对象ProxyObject。代理对象包含一个对实际对象的引用,并通过代理方法来控制对实际对象的访问。
在代理对象的 someMethod() 方法中,我们可以在调用实际对象方法之前执行一些前置操作,然后调用实际对象的方法,最后在调用之后执行一些后置操作。这样,代理对象可以在不修改实际对象的情况下添加额外的功能或控制访问权限。
代理模式可以应用于许多场景,例如:

  • 缓存代理:在访问实际对象之前,代理对象先检查缓存中是否存在结果,并返回缓存的结果,从而减少重复计算或请求。
  • 虚拟代理:延迟加载大型资源,例如在需要时才加载并显示图片。
  • 安全代理:控制对实际对象的访问权限,例如检查用户权限或身份验证。
  • 日志代理:记录实际对象的方法调用日志,用于调试或监控。

代理模式可以提供更灵活和可扩展的对象访问控制,同时保持代码的清晰性和可维护性。根据具体的应用场景,可以根据需要自定义代理对象的行为和操作。

观察者模式

观察者模式是一种设计模式,它建立了对象之间的一对多依赖关系,当一个对象状态发生改变时,其依赖的所有对象都会收到通知并自动更新。在前端开发中,观察者模式常用于实现事件订阅/发布系统或组件间的通信。以下是一个前端的观察者模式代码案例,附带注释说明:

// 前端观察者模式案例

// 观察者
class Observer {
  update(data) {
    // 当被观察者状态发生变化时,触发的更新操作
    // ...
  }
}

// 被观察者
class Observable {
  constructor() {
    this.observers = [];
  }

  addObserver(observer) {
    this.observers.push(observer);
  }

  removeObserver(observer) {
    const index = this.observers.indexOf(observer);
    if (index !== -1) {
      this.observers.splice(index, 1);
    }
  }

  notifyObservers(data) {
    this.observers.forEach(observer => {
      observer.update(data);
    });
  }

  // 改变状态的操作
  changeState(data) {
    // 执行状态改变的逻辑
    // ...

    // 通知所有观察者
    this.notifyObservers(data);
  }
}

// 创建观察者实例
const observer1 = new Observer();
const observer2 = new Observer();

// 创建被观察者实例
const observable = new Observable();

// 添加观察者
observable.addObserver(observer1);
observable.addObserver(observer2);

// 改变状态,触发观察者更新
observable.changeState(data);

在上述案例中,我们有一个观察者类Observer和一个被观察者类Observable。观察者可以订阅被观察者的状态变化,并在状态变化时执行相应的操作。
被观察者类维护了一个观察者列表,并提供了添加观察者、移除观察者和通知观察者的方法。当被观察者的状态发生改变时,它会遍历观察者列表,调用每个观察者的update() 方法,将变化的数据传递给观察者进行处理。
在使用观察者模式时,我们需要创建观察者实例和被观察者实例,并将观察者添加到被观察者的观察者列表中。当被观察者的状态发生改变时,通过调用 changeState() 方法来触发观察者的更新操作。
观察者模式可以帮助实现松耦合的组件间通信,使得组件之间更加灵活和可维护。通过使用观察者模式,可以将事件的订阅和发布的责任分离,提高代码的可扩展性和可重用性。

策略模式

策略模式是一种设计模式,它定义了一系列可相互替换的算法,并使得算法的选择与使用者分离。在前端开发中,策略模式常用于处理不同的业务规则或算法,并根据需要动态地选择和应用适当的策略。以下是一个前端的策略模式代码案例,附带注释说明:

// 前端策略模式案例

// 策略接口
class Strategy {
  execute(data) {
    // 执行策略的逻辑
    // ...
  }
}

// 策略实现:具体策略1
class ConcreteStrategy1 extends Strategy {
  execute(data) {
    // 具体策略1的执行逻辑
    // ...
  }
}

// 策略实现:具体策略2
class ConcreteStrategy2 extends Strategy {
  execute(data) {
    // 具体策略2的执行逻辑
    // ...
  }
}

// 环境类
class Context {
  constructor(strategy) {
    this.strategy = strategy;
  }

  setStrategy(strategy) {
    this.strategy = strategy;
  }

  executeStrategy(data) {
    this.strategy.execute(data);
  }
}

// 创建策略实例
const strategy1 = new ConcreteStrategy1();
const strategy2 = new ConcreteStrategy2();

// 创建环境实例
const context = new Context(strategy1);

// 使用具体策略1执行
context.executeStrategy(data);

// 切换策略为具体策略2
context.setStrategy(strategy2);

// 使用具体策略2执行
context.executeStrategy(data);

在上述案例中,我们有一个策略接口Strategy,它定义了策略类的执行方法。然后我们有两个具体的策略实现ConcreteStrategy1ConcreteStrategy2,它们分别实现了策略接口的执行方法,并提供了不同的执行逻辑。
接下来,我们有一个环境类Context,它包含了一个策略对象,并通过setStrategy()方法来动态地设置当前使用的策略。环境类的executeStrategy() 方法用于执行当前策略的逻辑。
在使用策略模式时,我们首先创建具体的策略实例。然后创建环境实例,并通过构造函数或setStrategy() 方法将具体策略实例设置为当前的策略。最后,调用环境实例的executeStrategy() 方法来执行当前策略的逻辑。
策略模式的优点在于可以根据需要动态地切换和应用不同的策略,使得算法的选择与使用者分离,提高代码的灵活性和可扩展性。策略模式适用于处理一组相关的算法或业务规则,并且这些算法或规则可以相互替换的情况。文章来源地址https://www.toymoban.com/news/detail-497915.html

到了这里,关于前端常用设计模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【设计模式之美】SOLID 原则之二:开闭原则方法论、开闭原则如何取舍

    具体的说,添加一个新的功能应该是,在已有代码基础上扩展代码(新增模块、类、方法等),而非修改已有代码(修改模块、类、方法等)。 举例说明: 现在,如果我们需要添加一个功能,当每秒钟接口超时请求个数,超过某个预先设置的最大阈值时,我们也要触发告警

    2024年01月25日
    浏览(52)
  • 【C++设计模式】单一职责原则

    2023年8月26日,周六上午 目录 概述 一个简单的例子 用单一职责原则来设计一个简单的学生管理系统 单一职责原则(Single Responsibility Principle,SRP),它是面向对象设计中的一个基本原则。 单一职责原则的核心思想是,一个类应该只有一个引起它变化的原因。 换句话说, 一个

    2024年02月11日
    浏览(41)
  • 设计模式和七大原则概述及单一职责原则详解

    设计模式的目的 编写软件过程中,程序员面临着来自,耦合性,内聚性以及可维护性,扩展性,重用性等方面的挑战。设计模式是为了让程序,具有更好的 1.代码重用性(相同代码,不用重复编写) 2.可读性(编程规范性,便于其他程序员的阅读和理解) 3.可扩展性(当需要增加新

    2024年02月12日
    浏览(43)
  • 【8】c++设计模式——>单一职责原则

    C++面向对象三大特性之一的 封装 指的就是将单一事物抽象出来组合成一个类,所以我们在设计类的时候每个类中处理的是单一事物而不是某些事物的集合。让类的功能单一,不让类与具体的事物耦合。 设计模式中所谓的单一职责原则,就是对一个类而言,应该仅有一个引起

    2024年02月07日
    浏览(39)
  • 前端设计模式和设计原则之设计原则

    1 开闭原则 该原则指出软件实体(类、模块、函数等)应该 对扩展开放,对修改关闭 。也就是说,在添加新功能时,应该通过扩展现有代码来实现,而不是直接修改已有的代码。这样可以确保现有代码的稳定性,并且减少对其他部分的影响。 在上述例子中,有一个原始功能

    2024年02月07日
    浏览(39)
  • 【设计模式之禅】单一职责

    最近前辈推荐我读《设计模式之禅》这本书,原因是我写的代码质量实在是一言难尽,开发速度很快,但是bug数就很多了,设计原则这种知识就需要掌握 写这篇文主要是记录自己的学习以及督促自己 第一章【单一职责】 从我理解的层面来谈谈单一原则:明确每个类每个方法

    2024年02月13日
    浏览(39)
  • 前端常用的设计模式

    设计模式:是一种抽象的编程思想,并不局限于某一特定的编程语言,而是在许多语言之间是相通的;它是软件设计中常见的问题的通用、可反复使用、多少人知晓的一种解决方案或者模板。一般对与从事过面向对象编程的人来说会更熟悉一些。 设计模式的意义:指导我们如

    2024年01月24日
    浏览(35)
  • 前端常用设计模式

    在上述案例中, UserInfoComponent 负责两个职责:显示用户信息和发送请求获取用户信息。如果我们将发送请求的逻辑提取到一个单独的服务或钩子函数中,可以更好地遵守单一职责原则。 在上述案例中,主题切换功能违反了开放封闭原则,因为每次添加新的主题都需要修改切

    2024年02月10日
    浏览(37)
  • 前端常用设计模式初探

    设计模式一直是程序员谈论的“高端”话题之一,总有一种敬而远之的心态。在了解后才知道在将函数作为一等对象的语言中,有许多需要利用对象多态性的设计模式,比如单例模式、 策略模式等,这些模式的结构与传统面向对象语言的结构大相径庭,实际上已经融入到了语

    2024年02月05日
    浏览(37)
  • 【设计模式】设计原则-开闭原则

    定义 作用 1、方便测试;测试时只需要对扩展的代码进行测试。 2、提高代码的可复用性;粒度越小,被复用的可能性就越大。 3、提高软件的稳定性和延续性,易于扩展和维护。 实现方式 通过“抽象约束、封装变化”来实现开闭原则。通过接口或者抽象类为软件实体定义一

    2024年02月15日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包