JS设计模式之适配器模式

来源:互联网 发布:决战武林进阶数据坐骑 编辑:程序博客网 时间:2024/05/17 19:18

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

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

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

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

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">loadMessage Sister Sonya</a></li><li class="thread"><a class="a" href="#" id="msg-2">loadMessage Lindsey Simon</a></li><li class="thread"><a class="a" href="#" id="msg-3">loadMessage Margaret Stoooart</a></li></ul><div id="message-pane"></div></div></body><script>  </script></html>

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

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


原创粉丝点击