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

yizhihongxing

深入理解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中位置与大小的获取方法

    当我们开发JavaScript程序时,经常需要获取页面元素的位置与大小,以便进行后续的操作。接下来,我将为大家介绍JS中获取元素位置与大小的方法。 获取元素位置 1. offsetTop和offsetLeft属性 offsetTop和offsetLeft是用来获取某个元素相对于其offsetParent元素(指具有定位属性的父元素)的左上角距离的。 cons…

    JavaScript 2023年6月10日
    00
  • js中prototype用法详细介绍

    “js中prototype用法详细介绍”的攻略如下: 1. 什么是prototype 在javascript中,每个对象有一个特殊的属性__proto__,指向其构造函数的原型对象(prototype)。原型对象中存储着对象的方法和属性。使用原型机制,可以使所有对象共享相同的属性和方法,而不必为每个对象创建副本。 2. 为什么需要prototype 在jav…

    JavaScript 2023年6月10日
    00
  • Javascript入门学习第一篇 js基础第1/2页

    下面我将详细讲解“Javascript入门学习第一篇 js基础第1/2页”的完整攻略。 一、前言 Javascript(简称JS)是一种脚本语言,旨在为 HTML 页面和浏览器提供交互性和动态性,是目前互联网上应用最广泛的编程语言之一。 本文是Javascript基础学习系列教程的第一篇,旨在帮助初学者掌握Javascript的基本概念和语法,为进一步学习J…

    JavaScript 2023年5月17日
    00
  • 在页面上点击任一链接时触发一个事件的代码

    要实现在页面上点击任一链接时触发一个事件的代码,可以通过以下步骤来实现: 第一步:添加一个事件监听器 在页面中添加一个事件监听器来监听所有a标签的点击事件,代码如下: document.addEventListener(‘click’, function(event) { if (event.target.tagName === ‘A’) { // 点击事件…

    JavaScript 2023年6月11日
    00
  • vue之带参数跳转打开新页面、新窗口

    我将为您讲解“Vue之带参数跳转打开新页面、新窗口”的完整攻略。 前言 在Vue开发过程中,难免会遇到需要在新页面或者新窗口中打开链接的场景。而且可能还需要携带参数。本文将为您介绍Vue中如何带参数跳转打开新页面、新窗口。 解决方案 路由跳转 在Vue中进行路由跳转,可以使用Vue Router实现。当需要携带参数时,我们可以在路由跳转时将参数以query(…

    JavaScript 2023年6月11日
    00
  • JS按钮连击和接口调用频率限制防止客户爆仓

    JS按钮连击和接口调用频率限制防止客户爆仓是前端开发中非常重要的两个问题,此处进行详细讲解。 JS按钮连击 在网页中,用户经常会通过点击按钮等界面元素执行某些操作。如果用户在短时间内多次连续点击同一个按钮,就会引发“按钮连击”问题。如何避免JS按钮连击问题呢?下面介绍几种常用的方法: 1. 禁用按钮 可以在按钮第一次点击时禁用按钮,在处理完当前请求后再重新启…

    JavaScript 2023年6月10日
    00
  • JavaScript使用localStorage存储数据

    以下是使用localStorage存储数据的完整攻略。 什么是localStorage? localStorage是一种客户端存储数据的方式,它可以在客户端本地存储数据,是一个只有浏览器端可以访问的本地存储器。localStorage可以使网页在下一次访问时获取我们之前保存的数据。 localStorage的使用步骤 1. 存储数据 在JavaScript中…

    JavaScript 2023年6月11日
    00
  • JS+jQuery实现注册信息的验证功能

    实现注册信息的验证功能是一个常见的前端开发需求,使用JS+jQuery可以简单且高效地实现。下面是一个完整攻略,包含了实现过程、代码示例以及注意事项。 实现过程 在页面中添加表单元素,如input和button,并为其添加id和name属性。 在一个JS文件中创建一个函数,用于获取表单元素的值并进行验证。可以使用jQuery的选择器来获取表单元素。 在验证函…

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