代码要写成别人看不懂的样子(六)

本篇文章参考书籍《JavaScript设计模式》–张容铭

前言

  由于现在网络的发展,访问量,需求量越来越高,很难再使用一台服务器解决所有请求了,这就需要设置专门功能的服务器,来处理专门的业务。比如一个大型应用中,地图功能需要配置一台地图服务器,实况功能需要配置一台媒体服务器,数据上传专门来一台服务器,数据库系统再来一台,管理这些服务器还需要一台。在一些高并发的地方,一台服务器处理不过来,要把请求分散到各个服务器上进行处理。

  服务器越来越多,不可避免地要考虑一个问题,跨域请求,跨域本身是一种安全策略,为了网络安全,不能直接请求非本服务器上的资源,甚至连本服务器上不同的端口,也不能直接访问。

  为了能正常请求到我们想要的东西,那我们就必须找一个代理,来帮我们达到目的。这就是今天的代理模式。

一、代理模式

  解决跨域时我们可以用一些小技巧,比如 a 标签的 src 属性,在跳转的时候就可以向其他服务器发送请求。这个请求只能是 get 。并且是单向的,没有响应数据。

//统计代理
var Count = (function() {
	var _img = new Image();
	//返回统计函数
	return function(param) {
		//统计请求字符串
		var str = 'http://www.count.com/a.gif?';
		//拼接字符串
		for(var i in param) {
			str += i + '=' + param[i];
		}
		//发送统计请求
		_img.src = str;
	}
})();

Count({num: 10});

  上面方法毕竟受限,我们还有一种通过 script 标签来完成代理, JSONP 方案

//前端浏览器页面
<script type="text/JavaScript">
//回调函数,打印出来请求数据与响应数据
function jsonpCallBAck(res, req) {
	console.log(res, req);
}
</script>
<script
	type="text/JavaScript"
	src="http://localhost/test/jsonp/php?callback=jsonp CallBack&data=getJsonPData">
</script>
//另外一个域下服务器请求接口
<?php
	/*后端获取请求字段,并生成返回内容*/
	$data = $_GET["data"];
	$callback = $_GET["callback"];
	echo $callback."('success', '".$data."')";
?>

  这种方式类似河上有一条小船,你把要发送的消息放到小船上,让小船带到对岸,然后对岸的人将数据放到船里带回来。这种方式需要其他域有一定的可靠性,因为不知道船会带回来什么。

  还有一种方式,应用的比较广泛,比如现在页面的请求在域X中,请求的地址为域 Y ,那么这两个不同的域会出现跨域问题,那么如果我现在 X 域中,中专门配置一个服务器 A 做代理,所以 X 的请求,先发送到 A 上,然后服务器之间通信是没有跨域问题的,就可以让 A 代理转发请求。

  现代常用的代理有 Nginx GO 等,大家感兴趣可以去看看,据大神说, GO 代理一个周末就能搞定。

二、装饰着模式

  前面的文章我们已经介绍过装饰者模式了,这里又拿出来,是为了给大家解释一个问题。我们先复习下,装饰者模式是可以不改变原有功能的情况下,增加一些新的功能。之前我们举的例子是在 Function 的原型上增加一个 before after 函数,让执行 函数的时候先执行 before 再执行 fucntion 最后再执行 after ,通过这种方法实现的装饰者。

  下面我们用一种新的实现形式,比如这里有个输入框,点击可以显示输入规则,然后来了个需求,不光要显示输入规则,还希望同时让输入框变为红色。

  修改很简单,找到对应的输入框,增加一个输入框颜色修改就可以了,但是我一个一面如果有很多输入框,都需要增加这个功能,这个时候一个一个修改,就很耗时耗力了。我们可以使用装饰者模式。

//装饰者模式
var decorator = function(input, fn) {
	//获取事件源
	var input = document.getElementById(input);
	//若事件源已经绑定事件
	if(typeof input.onclick === 'function') {
		//缓存事件原有回调函数
		var oldClickFn = input.onclick;
		//为事件定义新的事件
		input.onclick = function() {
			//事件原有回调函数
			oldClickFn();
			//新增回调函数
			fn();
		}
	} else {
		//直接为事件添加新增回调
		input.onclick = fn;
	}
	//其他事情
}

  使用的时候,只要把需要添加的输入框执行一下 decorator 函数就可以。

decorator('tel_input', function() {
	document.getElementById('tel_demo_text').style.border = '1px solid red';
});

  为什么要重新举一个装饰者模式的例子,主要是想让大家明白,设计模式是一种思想,这种思想不受代码限制,不是说我的代码必须要写的一摸一样,才算使用了设计模式,它是一种思维方式。正如本系列文章开篇提到的,设计模式是兵法,要学会兵法的精髓,按照兵法去思考而不是按照兵法做。

  之前介绍的那么多种设计模式里面,除了抽象工厂方法必须要用继承来实现,其余的每一种方法,都不是只有例子里的用法。可以展开自己的想象,很多时候你可能没注意,你已经在使用设计模式的思想来解决问题了。

三、桥接模式

  接下来介绍一个大家一定用过,只是当时不知道的设计模式。桥接模式,举个例子,有一行导航栏,要求鼠标悬浮的时候背景色变深,旁边的导航栏,要求鼠标经过的时候里面的字体颜色。功能差不多,但是又不一样,感觉能合到一起,但是又不知道怎么整合。

var spans = document.getElementByTagName('span');
spans[0].onmouseover = function() {
	this.style.color = 'red';
	this.style.background = '#ddd';
};
spans[0].onmouseout = function() {
	this.style.color = '#333';
	this.style.background = '#f5f5f5';
};

spans[1].onmouseover = function() {
	this.getElementByTagName('strong')[0].style.color = 'red';
	this.getElementByTagName('strong')[0].style.background = '#ddd';
};
spans[1].onmouseout = function() {
	this.getElementByTagName('strong')[0].style.color = '#333';
	this.getElementByTagName('strong')[0].style.background = '#f5f5f5';
};

  上面代码可以看出来,是有一部分冗余的,我们需要对事件的回调函数再处理一下。具体做法如下,我们需要创建一个函数,解除与事件的 this 耦合。

//抽象
function changeColor(dom, color, bg) {
	//设置元素字体
	dom.style.color = color;
	//设置元素的背景颜色
	dom.style.background = bg;
}

var spans = document.getElementByTagName('span');
spans[0].onmouseover = function() {
	changeColor(this, 'red', '#ddd');
};
spans[0].onmouseout = function() {
	changeColor(this, '#333', '#f5f5f5');
};

spans[1].onmouseover = function() {
	changeColor(this.getElementByTagName('strong')[0], 'red', '#ddd');
};
spans[1].onmouseout = function() {
	changeColor(this.getElementByTagName('strong')[0], '#333', '#f5f5f5');
};

  上面的桥接模式用起来,有没有一点像我们之前学习的适配器模式,两种模式总体上是有一点相似,毕竟桥接与适配器,本身中文意思就有相似之处,只不过适配器模式多用在接口转换上,而桥接的特点是实现层与抽象层的分离。

  重申一下,设计模式是思想,要学会按照设计模式思考问题,不要受上面样例的束缚。




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值