js设计模式——代理模式(读书JavaScript设计模式与开发实战笔记02)

代理模式

代理模式顾名思义,就是通过一个代理去处理问题,例如黑道头子去买军火,一般都是让自己的头号手下去买,自己不参与实际交易~~

虚拟代理

我们先从常见的图片占位图片代理来说明。
通常情况下,我们加载图片的姿势是这样的。

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
</head>

<body>
	<!-- https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg -->
	<!-- https://www.baidu.com/img/xinshouye_4d9e7ecaa1b5f78475bf13965c6142d1.png -->
	<img id="image" src="" alt="">
	<script>
		var mgImage = (function(){
			var img = document.getElementById('image');
			// 因为我们需要一个方法 去供代理使用,所以这里返回的是对象。
			return {
				setImage: function(src){
					img.src = src;
				}
			}
		})();
		mgImage.setImage('https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg');

	</script>
</body>

</html>

没错,打开非常卡,因为我用的是一个外国网站的图片。
使用代理占位图片来加载就是一个非常好的方法。如下:

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
</head>

<body>
	<!-- https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg -->
	<!-- https://www.baidu.com/img/xinshouye_4d9e7ecaa1b5f78475bf13965c6142d1.png -->
	<img id="image" src="" alt="">
	<script>
		var mgImage = (function(){
			var img = document.getElementById('image');
			return {
				setImage: function(src){
					// 2.设置成功,显示占位图片。
					img.src = src;
				}
			}
		})();

		var poxyImge = (function(){
			// 怎样判断我们需要的图片加载完成,首先创建一个图片实例poxyImg,用onload判断。
			var poxyImg= new Image();
			poxyImg.onload = function(){
				// 4.当真实图片地址加载完毕,添加到body的img标签里,完成代理。
				mgImage.setImage(this.src)
			}
			return {
				setImage: function(src) {
					// 1.先给img加载占位图片。
					mgImage.setImage('https://www.baidu.com/img/xinshouye_4d9e7ecaa1b5f78475bf13965c6142d1.png');
					// 3.给poxyImg实例添加真实图片地址
					poxyImg.src =src;
				}
			}
		})()
		poxyImge.setImage('https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg');

	</script>
</body>

</html>

当然我们也可以放在一个函数当中,这样就违反了单一原则和开放封闭原则,上面的代理模式,如果我们以后不需要这个图片占位,直接用mgImage函数调用方法就可以了。
如果不用代理模式如下:

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
</head>

<body>
	<!-- https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg -->
	<!-- https://www.baidu.com/img/xinshouye_4d9e7ecaa1b5f78475bf13965c6142d1.png -->
	<img id="image" src="" alt="">
	<script>
		var mgImage= (function(){
			var img = document.getElementById('image');
			var poxyImg = new Image;	
			poxyImg.onload = function(){
				img.src = this.src
			}
			return {
				setImage: function(src){
					img.src = 'https://www.baidu.com/img/xinshouye_4d9e7ecaa1b5f78475bf13965c6142d1.png';
					poxyImg.src = src;
				}
			}
		})();	
		mgImage.setImage('https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-747189.jpg')
	</script>
</body>

</html>

这样也能完成,但是对于以后的维护成本将会提升很多,因为要去mgImage函数中去修改原有的代码,是非常不划算的,而且容易产生BUG。

缓存代理

常常用于比较大的计算开销,如果传入的参数一致,则直接返回结果,无需计算。
比方说如下栗子,

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
</head>

<body>
	<script>
		var mult =  function () {
			console.log('start');
			var a = 1;
			for (var i = 0; i < arguments.length; i++) {
				a = a*arguments[i];
			}
			return a;
		}
		var poxyMult = (function () {
			var cache = {};
			return function () {
				// 定义对象KEY
				var args = Array.prototype.join.call(arguments, ',');
				// 判断KEY是否存在,不存在,新建一个key value
				if (!cache[args]) {
					cache[args] = mult.apply(this, arguments)
				}
				// 返回当前key 对应的value
				return cache[args];
			}
		})()
		var num = poxyMult(1,2,4,9); // 72
		var num1 = poxyMult(1,2,4,9); //72
	</script>
</body>

</html>

上面就使用了缓存代理,如果传入参数一样的情况下,会直接返回cache里面的值,当然这样写的话,我们只能计算乘积,其实我们可以进行解耦,在原先的poxyMult中,我们不仅进行了缓存,还把mult函数直接绑定在里面,这样是不好的,我们改写下。

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
</head>

<body>
	<script>
		var mult =  function () {
			console.log('start');
			var a = 1;
			for (var i = 0; i < arguments.length; i++) {
				a = a*arguments[i];
			}
			return a;
		}
		var createProxyFactory = function (fn) {
			var cache = {};
			return function () {
				var args = Array.prototype.join.call(arguments, ',');
				if (!cache[args]) {
					cache[args] = fn.apply(this, arguments)
				}
				return cache[args];
			}
		}
		var add =  function () {
			console.log('start');
			var a = 1;
			for (var i = 0; i < arguments.length; i++) {
				a = a + arguments[i];
			}
			return a;
		}
		var poxyMult = createProxyFactory(mult)
		var poxyAdd = createProxyFactory(add)
		var num = poxyMult(1,2,4,9); // 72
		var num1 = poxyAdd(1,2,4,9); // 17
	</script>
</body>

</html>

改写后的函数,我们新增一个ADD的计算函数,直接将函数传入createProxyFactory函数中,就实现了加法的缓存,这样我们就能实现多种计算的缓存。
这也是实现面向对象的开放封闭原则。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值