深入理解JavaScript系列(31):设计模式之代理模式详解

深入理解JavaScript系列(31):设计模式之代理模式详解

概述

代理模式是一种结构型模式,其中一个对象充当另一个对象的接口,以控制对该对象的访问。 这种类型的设计模式属于结构模式,它对对象进行组合,以提供新的功能,同时使代码更易于维护。

在 JavaScript 中,代理模式允许我们在运行时动态地创建对象并控制其行为。 代理可以隔离对实际对象的访问,并对外部世界提供它自己的访问方式,以限制直接访问实际对象。

代理模式的实现

代理模式通过创建代理对象对访问对象进行控制,代理对象与实际对象具有相同的接口,开发者可以通过代理对象访问实际对象。

代理对象

代理对象的作用是隐藏实际对象,以允许开发者访问实际对象的方法或属性,并在访问之前对访问请求进行处理。

代理对象与实际对象通常实现相同的接口,以便开发者可以在无需了解实际对象的情况下,使用代理对象访问实际对象。

class RealSubject {
  someOperation() {
    console.log("RealSubject.someOperation()");
  }
}

class ProxySubject {
  constructor(realSubject) {
    this.realSubject = realSubject;
  }

  someOperation() {
    console.log("ProxySubject.someOperation()");
    //handle the privilege to real object
    this.realSubject.someOperation();
  }
}

// Client
const realSubject = new RealSubject();
const proxySubject = new ProxySubject(realSubject);
proxySubject.someOperation();

保护代理

保护代理可以控制实际对象对内部状态的访问,如果属性或者方法不应该被外部对象访问,可以使用保护代理。

下面的例子中,我们使用保护代理来防止直接访问 privateMethod 方法

class RealSubject {
  someOperation() {
    console.log("RealSubject.someOperation()");
  }

  privateMethod() {
    console.log("RealSubject.privateMethod()");
  }
}

class ProxySubject {
  constructor(realSubject) {
    this.realSubject = realSubject;
  }

  someOperation() {
    console.log("ProxySubject.someOperation()");
    //handle the privilege to real object
    this.realSubject.someOperation();
    //Cannot access to privateMethod from outside
  }
}

// Client
const realSubject = new RealSubject();
const proxySubject = new ProxySubject(realSubject);
proxySubject.someOperation();

虚拟代理

虚拟代理是一种惰性加载模式,可以通过避免初始化真正对象来减少系统资源的使用。

下面的例子中,我们使用虚拟代理来加载视频

class VideoPlayer {
  constructor(video) {
    this.video = video;
  }

  play() {
    console.log(`Playing video: ${this.video.name}`);
  }
}

class VideoPlayerProxy {
  constructor(video) {
    this.video = video;
  }

  play() {
    if (!this.videoPlayer) {
      // Initialize the video player only when the user wants to play video
      this.videoPlayer = new VideoPlayer(this.video);
    }
    this.videoPlayer.play();
  }
}

// Client
const video = { name: "Introduction to Design Patterns" };
const videoPlayerProxy = new VideoPlayerProxy(video);
videoPlayerProxy.play();

总结

代理模式提供了访问受控对象的另一种方法,可以使用代理实现额外的功能或提供额外的保护。代理模式是一种非常常见的设计模式,它可以在需要对对象进行访问控制,缓存或记录日志时非常有用。

示例 1:代理模式用于日志系统

class BitcoinPrice {
  constructor() {}

  async getBitcoinPriceByCurrencyCode(currencyCode) {
    const response = await fetch(
      `https://api.coindesk.com/v1/bpi/currentprice/${currencyCode}.json`
    );
    const data = await response.json();
    return data.bpi[currencyCode].rate_float;
  }
}

class BitcoinPriceProxy {
  constructor() {
    this.bitcoinPrice = new BitcoinPrice();
  }

  async getBitcoinPriceByCurrencyCode(currencyCode) {
    const price = await this.bitcoinPrice.getBitcoinPriceByCurrencyCode(
      currencyCode
    );
    console.log(`Bitcoin price for ${currencyCode} is $${price}`);
    return price;
  }
}

// Client
const bitcoinPriceProxy = new BitcoinPriceProxy();
bitcoinPriceProxy.getBitcoinPriceByCurrencyCode("USD");

示例 2:代理模式用于缓存系统

class SomeContent {
  constructor(contentId) {
    this.contentId = contentId;
    this.content = null;
  }

  async getContent() {
    // simulate loading content from a database
    await new Promise((resolve) => setTimeout(resolve, 3000));
    return `<html><body>Content for page ${this.contentId}</body></html>`;
  }
}

class CachedContent {
  constructor(content) {
    this.content = content;
    this.cachedContent = null;
  }

  async getCachedContent() {
    if (!this.cachedContent) {
      console.log("Cache miss, fetching content...");
      this.cachedContent = await this.content.getContent();
    }
    console.log("Cache hit, returning content from cache...");
    return this.cachedContent;
  }
}

// Client
const contentId = 3;
const content = new SomeContent(contentId);
const cachedContent = new CachedContent(content);
console.log("First fetch:");
await cachedContent.getCachedContent();
console.log("Second fetch:");
await cachedContent.getCachedContent();

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解JavaScript系列(31):设计模式之代理模式详解 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • js时间戳与日期格式之间转换详解

    关于“js时间戳与日期格式之间转换详解”这一话题,我将从以下几个方面进行详细讲解: 时间戳(Timestamp)的定义 JavaScript中的时间戳 JavaScript中的日期格式 时间戳与日期格式之间的相互转换 时间戳(Timestamp)的定义 在计算机的领域中,时间戳(Timestamp)是指某个被定义为某个特定事件发生的精确时间点所对应的数字或字…

    JavaScript 2023年5月27日
    00
  • 微信小程序-详解微信登陆、微信支付、模板消息

    微信小程序-详解微信登陆、微信支付、模板消息 本攻略将详细介绍微信小程序中微信登陆、微信支付、模板消息的使用方法。 微信登陆 微信登陆可用于用户授权登陆、获取用户信息。 1. 微信开放平台配置 在微信开放平台中,配置小程序的“登陆授权”和“网页授权”,并获取小程序appid、appsecret。 2. 小程序配置 在小程序中,使用wx.login获取临时登录…

    JavaScript 2023年6月10日
    00
  • js捆绑TypeScript声明文件的方法教程

    下面是详细讲解“js捆绑TypeScript声明文件的方法教程”的完整攻略: 什么是TypeScript声明文件? TypeScript声明文件是描述JavaScript代码的接口和类型的文件,可以方便地为JavaScript代码提供静态类型检查和智能提示。 捆绑TypeScript声明文件的方法 方法一:使用@types包 @types包是一种官方推荐的捆…

    JavaScript 2023年5月27日
    00
  • 浅谈JavaScript对象的创建方式

    JavaScript 是一种面向对象的编程语言,对象是它的核心。在 JavaScript 中,对象可以通过不同的方式进行创建。下面将详细讲解 JavaScript 对象的创建方式。 字面量创建对象 JavaScript 对象可以通过字面量的方式创建。字面量创建的对象很简单,只需要 {} 这个大括号。在这个大括号中填写数据,即可创建一个对象,它的属性和值由大括…

    JavaScript 2023年5月18日
    00
  • js实现浏览本地文件并显示扩展名的方法

    要实现浏览本地文件并显示扩展名的方法,需要使用HTML5 File API和JavaScript。下面是具体步骤: 创建html模板,添加文件输入框 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>浏览本地文…

    JavaScript 2023年5月27日
    00
  • 快速解决js动态改变dom元素属性后页面及时渲染的问题

    要想实现JS动态改变DOM元素属性后页面及时渲染,我们需要使用JS操作DOM元素的API,以及合理控制DOM的渲染。 以下是实现此功能的完整攻略: 1. 获取DOM元素 首先,我们需要获取需要改变属性的DOM元素。可以通过各种方式获取,比如通过ID、class、元素标签名等。 代码示例 // 通过ID获取DOM元素 let el = document.get…

    JavaScript 2023年6月10日
    00
  • JavaScript的ExtJS框架中表格的编写教程

    下面是JavaScript的ExtJS框架中表格的编写教程的完整攻略。 1. 概述 JavaScript的ExtJS框架提供了丰富的表格组件,能够满足各种需求。本攻略将详细介绍如何在ExtJS中编写表格组件。 2. 表格的基本结构 表格组件由表头和表格数据两部分组成。表头定义表格列的名称和宽度,表格数据为表格中实际展示的数据。 3. 表头的编写 表头的编写需…

    JavaScript 2023年6月10日
    00
  • JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)

    JavaScript中最容易混淆的作用域、提升、闭包知识详解 作用域 JavaScript采用词法作用域,即函数的作用域在函数定义时就已经确定了,不会随着函数调用的位置改变。因此,JavaScript中存在全局作用域和函数作用域。 全局作用域 全局作用域是指在代码的任何位置都可以访问的变量、函数和对象,它是在所有函数外部定义的作用域。 以下是一个示例,全局作…

    JavaScript 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部