首页 web前端 js教程 学习JavaScript设计模式之代理模式_javascript技巧

学习JavaScript设计模式之代理模式_javascript技巧

May 16, 2016 pm 03:20 PM
javascript 代理模式 设计模式

  • 明星都有经纪人作为代理。如果请明星办一场商演,只能联系其经纪人,经纪人会把商演的细节和报酬谈好,再把合同交给明星签。

一、定义

代理模式:为一个对象提供一个代用品或占位符,以便控制对它的访问。
代理分为:保护代理和虚拟代理
保护代理:用于控制不同权限的对象对目标对象的访问,在JavaScript中很难判断谁访问了某个对象,所以保护代理很难实现。

二、图片预加载(最常见的虚拟代理应用场景)

图片预加载是一种常用技术,如果直接给某个img标签节点设置src属性,由于图片过大或者网络不佳,图片的位置往往有段时间会有空白。常见的做法事先用一张loading图片占位,然后异步加载图片,待图片加载完成,把其填充到img节点里。
实现原理:
创建一个Image对象:var a = new Image();
定义Image对象的src: a.src = “xxx.gif”;
这样做就相当于给浏览器缓存了一张图片。

可通过Image对象的complete属性来检测图像是否加载完成。每个Image对象都有一个complete属性,当图像处于装载过程中时,该属性值false,当发生了onload、onerror、onabort中任何一个事件后,则表示图像装载过程结束,此时complete属性为true。

(1)非代理实现

var myImage = (function() {
  var imgNode = document.createElement("img");
  document.body.appendChild(imgNode);
  var img = new Image();

  img.onload = function() {
    imgNode.src = img.src;
  };

  return {
    setSrc: function(src) {
      imgNode.src = "./images/loading.gif";
      img.src = src;
    }
  }
})();

myImage.setSrc("./images/originImg.png");

登录后复制

(2)代理实现

// 创建图片DOM
var myImage = (function() {
  var imgNode = document.createElement("img");
  document.body.appendChild(imgNode);

  return {
    setSrc: function(src) {
      imgNode.src = src;
    }
  };
})();

// 代理
var proxyImage = (function() {
  var img = new Image();

  img.onload = function() {
    myImage.setSrc(this.src);  // this指向img!img加载完成后,将img.src传递给myImage
  };

  return {
    setSrc: function(src) {
      myImage.setSrc("./images/loading.gif");   // loading
      img.src = src;
    }
  };
})();

proxyImage.setSrc("./images/originImg.png");

登录后复制

使用代理模式的好处:使每个函数功能单一,实现对象设计的“单一职责原则”!

三、文件同步

假设我们在做一个文件同步功能,当选中checkbox时候,它对应的文件就会被同步到另外一台服务器。

<body>
    <input type="checkbox" id="1" />文件1
    <input type="checkbox" id="2" />文件2
    <input type="checkbox" id="3" />文件3
    <input type="checkbox" id="4" />文件4
    <input type="checkbox" id="5" />文件5
    <input type="checkbox" id="6" />文件6
  </body>
登录后复制

没选中一个checkbox就同步一次,显然不太合理。因为在web开发中,最大的开销就是网络请求。
解决方案:通过一个代理函数来收集一段时间之内的请求,然后一次性发给服务器。

var synchronousFile = function(id) {
  console.log("开始同步文件,id为:" + id);
};

var proxySynchonousFile = (function() {
  var cache = [],   // 保存本次需要同步文件的id
    timer;     // 定时器

  return function(id) {
    cache.push(id);
    if(timer) { 
      // 不要覆盖已经启动的定时
      return;
    }

    timer = setTimeout(function(){
      synchronousFile(cache.join(","));
      clearTimeout(timer);
      timer = null;
      cache.length = 0;  // 清空缓存
    }, 2000);
  }
})();

var checkboxs = document.getElementsByTagName("input");

for(var i = 0, c; c = checkboxs[i]; i++) {
  c.onclick = function() {
    if(this.checked === true) {
      proxySynchonousFile(this.id);
    }
  }
}

登录后复制

四、缓存代理–计算乘积(序列一模一样)

var mult = function() {
  var result = 1;
  for(var i = 0, l = arguments.length; i < l; i++) {
    result= result * arguments[i];
  }
  return result;
};

var proxyMult = (function() {
  var cache = {};   // {"1,2,3": 6}
  return function() {
    var args = Array.prototype.join.call(arguments, ",");
    if(args in cache) {
      return cache[args];
    }
    return cache[args] = mult.apply(this, arguments);
  }
})();

console.log(proxyMult(1, 2, 3));

// 改造:

var proxyFactory = function(fn) {
  var cache = {};
  return function() {
    var args = Array.prototype.join.call(arguments, ",");
    if(args in cache) {
      return cache[args];
    }
    return cache[args] = fn.apply(this, arguments);
  }  
};

console.log(proxyFactory(mult)(1, 2, 3));
登录后复制

希望本文所述对大家学习javascript程序设计有所帮助。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Java框架中设计模式与架构模式的区别 Java框架中设计模式与架构模式的区别 Jun 02, 2024 pm 12:59 PM

在Java框架中,设计模式和架构模式的区别在于:设计模式定义了在软件设计中解决常见问题的抽象解决方案,关注类和对象之间的交互,如工厂模式。架构模式定义了系统结构和模块之间的关系,关注系统组件的组织和交互,如分层架构。

Java设计模式之装饰器模式剖析 Java设计模式之装饰器模式剖析 May 09, 2024 pm 03:12 PM

装饰器模式是一种结构型设计模式,允许动态添加对象功能,无需修改原始类。它通过抽象组件、具体组件、抽象装饰器和具体装饰器的协作实现,可以灵活扩展类功能,满足变化的需求。示例中,将牛奶和摩卡装饰器添加到Espresso,总价为2.29美元,展示了装饰器模式在动态修改对象行为方面的强大功能。

PHP 设计模式实战案例解析 PHP 设计模式实战案例解析 May 08, 2024 am 08:09 AM

1.工厂模式:分离对象创建和业务逻辑,通过工厂类创建指定类型的对象。2.观察者模式:允许主题对象通知观察者对象其状态更改,实现松耦合和观察者模式。

设计模式如何应对代码维护难题 设计模式如何应对代码维护难题 May 09, 2024 pm 12:45 PM

设计模式通过提供可重用和可扩展的解决方案来解决代码维护难题:观察者模式:允许对象订阅事件,并在事件发生时收到通知。工厂模式:提供了一种创建对象的集中式方式,而无需依赖具体类。单例模式:确保一个类只有一个实例,用于创建全局可访问的对象。

Java设计模式之适配器模式的妙用 Java设计模式之适配器模式的妙用 May 09, 2024 pm 12:54 PM

适配器模式是一种结构型设计模式,允许不兼容对象协同工作,它将一个接口转换为另一个,使对象能够顺利交互。对象适配器通过创建包含被适配对象的适配器对象,并实现目标接口,实现适配器模式。在一个实战案例中,通过适配器模式,客户端(如MediaPlayer)可以播放高级格式的媒体(如VLC),尽管其本身仅支持普通媒体格式(如MP3)。

PHP设计模式:测试驱动开发实践 PHP设计模式:测试驱动开发实践 Jun 03, 2024 pm 02:14 PM

TDD用于编写高质量PHP代码,步骤包括:编写测试用例,描述预期功能并使其失败。编写代码,仅使测试用例通过,无需过分优化或详细设计。测试用例通过后,优化和重构代码以提高可读性、可维护性和可扩展性。

java框架中代理模式的优缺点有哪些? java框架中代理模式的优缺点有哪些? Jun 03, 2024 am 09:34 AM

代理模式是一种Java框架设计模式,通过创建代理对象在客户端和目标对象之间进行中介。它的优势包括:保护目标对象,提供数据完整性和安全性;控制对目标的访问,实现权限控制和安全措施;增强目标行为,添加额外功能如日志记录、缓存和事务管理;简化测试,便于mocking和stubbing目标。然而,代理模式也存在劣势:开销:创建和维护代理对象可能降低性能;复杂性:需要深入理解设计模式;限制对目标的访问,可能在某些情况下不合适。

Guice框架中设计模式的应用 Guice框架中设计模式的应用 Jun 02, 2024 pm 10:49 PM

Guice框架应用了多项设计模式,包括:单例模式:通过@Singleton注解确保类只有一个实例。工厂方法模式:通过@Provides注解创建工厂方法,在依赖注入时获取对象实例。策略模式:将算法封装成不同策略类,通过@Named注解指定具体策略。

See all articles