JS设计模式之适配器模式

适配器模式用在现有接口跟不兼容的类和接口之间进行适配。用一个新的接口包装另一个对象。

适配器用在协调两个不同的接口。与门面模式的区别:

门面模式展现的是一个简化的接口,只是对代码及接口起到简化作用,不提供额外的选择。

适配器模式则是需要把一个接口转换为另外一个接口,完全保留接口,并且不会简化接口。

var clientObject={
    string1:'foo',
	string2:'bar',
	string3:'baz'
};
function interfaceMethod(str1,str2,str3){
    ...
}

function clientToInterfaceAdapter(o){
    interfaceMethod(o.str1,o.str2,o.str3);
}
clientToInterfaceAdapter(clientObject);

对于clientObject作为参数传递给interfaceMethod,需要使用适配器。


示例:

function $(){
    var elements=[];
	for(var i=0;i<arguments.length;i++){
	    var element=arguments[i];
		if(typeof element == 'string')
		    element = document.getElementById(element);
		if(arguments.length == 1)
		    return element;
		elements.push(element);
	}
	return elements;
}

function get(el){
    if(typeof el == 'string')
	    return document.getElementById(el);
    if({}.toString.call(el) == '[object Array]'){
	    var c = [];
		for(var i=0,len=el.length;i<len;++i){
		    c[c.length]=get(el[i]);
		}
		return c;
	}
	if(el){
	    return el;
	}
	return null;
}

$函数的参数可以是一个或者多个,然而get函数只有一个,可以是个字符串、HTML元素,或者是字符串跟HTML元素组成的数组。适配这两个方法如下:

function $ToGet(){
	    return get(arguments);
	}
    function GetTo$(el){
	    return $.apply(window,el instanceof Array?el:[el]);
	} 

示例:适配电子邮件API

<html>
<head>
<script>
function $(id){
    return typeof id == 'string'?document.getElementById(id):id;
}
function getElementsByClass(){
    var ele = [];
    function getClassElement(className,el){
	    var ob = [];
		el = el||document;
	    var nodes = el.getElementsByTagName('*');
        for(var i=0, len=nodes.length; i < len; i++){
		    if(nodes[i].className == className)
			    ob.push(nodes[i]);
		}
        return ob; 		
	}
    if(arguments.length == 1){
	    return getClassElement(arguments[0]);
	}else{
	    var prev = getClassElement(arguments[0]),next = [];
		for(var j = 0, length = prev.length; j < length; j++){
		    var r = getClassElement(arguments[1], prev[j]);
			next=next.concat(r);
		}
		return next;
	}
}
function addEvent(node, type, fn){
     if(node.addEventListener){
	    node.addEventListener(type, fn, false);
	 }else if(node.attachEvent){
	    node.attachEvent('on'+type,fn)
	 }else{
	    node['on'+type] = fn;
	 }
}
var DED = {};
DED.util = {
    substitute:function (s, o){
	    return s.replace(/{([^{}]*)}/g,function (a, b){
		    var r = o[b];
			return typeof r == 'string' ||typeof r == 'number' ? r : a;
		});
	},
	asyncRequest:(function(){
	    function handleReadyState(o, callback) {
		    var poll = window.setInterval(function(){
			    if(o&&o.readyState == 4){
				    window.clearInterval(poll);
					if(callback)
					    callback(o);
				}
			},50);
		}
		var getXHR = function(){
		    var http;
			try {
			    http = new XMLHttpRequest;
				getXHR = function(){
				    return new XMLHttpRequest;
				};
			}
			catch(e) {
			    var msxml = [
				    'MSXML2.XMLHTTP.3.0',
					'MSXML2.XMLHTTP',
					'Microsoft.XMLHTTP'
				];
				for(var i = 0, len = msxml.length; i < len; ++i){
				    try{
					    http = new ActiveXObject(msxml[i]);
						getXHR = function() {
						    return new ActiveXObject(msxml[i]);
						};
						break;
					}
					catch(e){}
				}
			}
			return http;
		};
		return function(method, uri, callback, postData){
		    var http = getXHR();
			http.open(method, uri, true);
			handleReadyState(http, callback);
			http.send(postData || null);
			return http;
		};
	})()	
};
var dedMail = (function(){
    function request(id, type, callback){
	    DED.util.asyncRequest(
		    'GET',
			'new/index',
			function(o) {
			    callback(o.responseText);
			}
		);
	}
	return {	
	    getMail: function(id, callback){
		    request(id, 'all', callback);
		},
		sendMail: function(body, recipient){
				
		},
		save: function(id) {
		
		},
		move: function(id, destination){
		
		},
		archive: function(id) {
		 
		},
		trash: function(id) {
		
		},
		reportSpam: function(id) {
		
		},
		formatMessage: function(e) {
		    var e = e || window.event;
			try {
			    e.preventDefault();
			}
			catch(ex) {
			    e.returnValue = false;
			}
			var targetEl = e.target || e.srcElement;
			var id = targetEl.id.toString().split('-')[1];
			dedMail.getMail(id, function(msgObject) {
			     var resp = eval('('+msgObject+')');
				 var details = '<p><strong>From:</strong>{from}<br>';
				 details += '<strong>Sent:</strong>{date}</p>';
				 details += '<p><strong>Message</strong><br>';
				 details += '{message}</p>';
				 $('message-pane').innerHTML = DED.util.substitute(details, resp);
			});
		}
	};
})();
addEvent(window, 'load', function(){
    var threads = getElementsByClass('thread', 'a');
	for(var i = 0, len=threads.length; i<len; i++){
	    addEvent(threads[i], 'click', dedMail.formatMessage);
	}
});
var fooMail = {}
//fooMail.getMail方法接受两个参数 一是ID 二是回调函数 并且函数处理过 类似
//function(text){ $('message-pane').innerHTML =text;}
var dedMailToFoolMail = {};
dedMailToFoolMail.getMail = function(id, callback){
    dedMail.getMail(id, function(msgObject) {
			     var resp = eval('('+msgObject+')');
				 var details = '<p><strong>From:</strong>{from}<br>';
				 details += '<strong>Sent:</strong>{date}</p>';
				 details += '<p><strong>Message</strong><br>';
				 details += '{message}</p>';
				 callback(DED.util.substitute(details, resp));
			});
};
fooMail = dedMailToFoolMail;
fooMail.getMail("a",function(text){$('message-pane').innerHTML=text;});
</script>
</head>
<body>
	<div id="doc">
		<h1>Email Application Interface</h1>
		<ul>
			<li class="thread"><a class="a" href="#" id="msg-1">load
					Message Sister Sonya</a></li>
			<li class="thread"><a class="a" href="#" id="msg-2">load
					Message Lindsey Simon</a></li>
			<li class="thread"><a class="a" href="#" id="msg-3">load
					Message Margaret Stoooart</a></li>
		</ul>
		<div id="message-pane"></div>
	</div>
</body>
<script>
  </script>
</html>

这个例子很明显展示出当接口类型不一样的时候,通过适配协调的方式,完成接口的通用,增加代码的复用量。

适配器在当前条件下,框架层出不穷,又不统一的情况下,避免大规模改写代码,用新的接口对不适合的接口进行包装,协调语法的差异。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值