代理模式

代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。

保护代理和虚拟代理

  • 代理 B 可以帮助 A 过滤掉一些请求,这种请求就可以直接在代理 B 处被拒绝掉。这种代理叫作保护代理
  • 虚拟代理把一些开销很大的对象,延迟到 真正需要它的时候才去创建。

保护代理用于控制不同权限的对象对目标对象的访问,但在 JavaScript并不容易实现保护代 理,因为我们无法判断谁访问了某个对象。而虚拟代理是常用的一种代理模式

虚拟代理实现图片预加载

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 );
		}
		return {
			setSrc: function( src ){
				myImage.setSrc( 'file:// /C:/Users/svenzeng/Desktop/loading.gif' );
				img.src = src;
			}
		}
	})();
	proxyImage.setSrc( 'http:// imgcache.qq.com/music/photo/k/000GGDys0yA0Nk.jpg' );

代理的意义

单一职责原则

  • 单一职责原则指的是,就一个类(通常也包括对象和函数等)而言,应该仅有一个引起它变 化的原因。如果一个对象承担了多项职责,就意味着这个对象将变得巨大,引起它变化的原因可 能会有多个。面向对象设计鼓励将行为分布到细粒度的对象之中,如果一个对象承担的职责过多, 等于把这些职责耦合到了一起,这种耦合会导致脆弱和低内聚的设计。当变化发生时,设计可能 会遭到意外的破坏。

实际上,我们需要的只是给 img 节点设置 src,预加载图片只是一个锦上添花的功能。如果 能把这个操作放在另一个对象里面,自然是一个非常好的方法。于是代理的作用在这里就体现出 来了,代理负责预加载图片,预加载的操作完成之后,把请求重新交给本体 MyImage。

纵观整个程序,我们并没有改变或者增加 MyImage 的接口,但是通过代理对象,实际上给系 统添加了新的行为。这是符合开放—封闭原则的。给 img 节点设置 src 和图片预加载这两个功能, 被隔离在两个对象里,它们可以各自变化而不影响对方。何况就算有一天我们不再需要预加载, 那么只需要改成请求本体而不是请求代理对象即可。 (使用myImage.setSrc()方法即可)

缓存代理

缓存代理可以为一些开销大的运算结果提供暂时的存储,在下次运算时,如果传递进来的参 数跟之前一致,则可以直接返回前面存储的运算结果。

var mult = function(){
		console.log( '开始计算乘积' );
		var a = 1;
		for ( var i = 0, l = arguments.length; i < l; i++ ){
			a = a * arguments[i];
		}
		return a;
	};
	mult( 2, 3 ); // 输出:6
	mult( 2, 3, 4 ); // 输出:24
	//现在加入缓存代理函数:

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

	proxyMult( 1, 2, 3, 4 ); // 输出:24
	proxyMult( 1, 2, 3, 4 ); // 输出:24

用高阶函数动态创建代理

计算方法被当作参数传入一个专门用于创建缓存代理的工厂中, 这样一来,我们就可以为乘法、加 法、减法等创建缓存代理:

/**************** 计算乘积 *****************/
	var mult = function(){
		var a = 1;
		for ( var i = 0, l = arguments.length; i < l; i++ ){
			a = a * arguments[i];
		}
		return a;
	};
	/**************** 计算加和 *****************/
	var plus = function(){
		var a = 0;
		for ( var i = 0, l = arguments.length; i < l; i++ ){
			a = a + arguments[i];
		}
		return a;
	};
	/**************** 创建缓存代理的工厂 *****************/
	var createProxyFactory = 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 );
		}
	};

	var proxyMult = createProxyFactory( mult ),
	proxyPlus = createProxyFactory( plus );
	alert ( proxyMult( 1, 2, 3, 4 ) ); // 输出:24
	alert ( proxyMult( 1, 2, 3, 4 ) ); // 输出:24
	alert ( proxyPlus( 1, 2, 3, 4 ) ); // 输出:10
	alert ( proxyPlus( 1, 2, 3, 4 ) ); // 输出:10
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值