zoukankan      html  css  js  c++  java
  • JavaScript设计模式(4)-桥接模式

    桥接模式

    在设计一个 Js API 时,可用来弱化它与使用它的类和对象之间的耦合

    1. 事件监听器的回调函数

    function getBeerById(id, callback) {
        asyncRequest('GET', 'beer.uri?id=' + id, function(res){
            callback(resp.responseText)
        })
    }
    
    function getBeerByIdBridge (e) {   // 桥接元素:事件监听器的回调函数
    
        // 避免把 this.id 耦合到函数 getBeerById 中
        getBeerById(this.id, function(beer) {
            console.log('Requested Beer: ' + beer)
        })
    }
    
    addEvent(element, 'click', getBeerByIdBridge);
    

    2. 桥接性函数:特权函数

    var Public = function() {
        var secret = 3;
        this.privilegedGetter = function() {
            return secret
        }
    }
    
    // usage
    var o = new Public;
    var data = o.privilegedGetter()
    

    3. 用桥接模式联结多个类

    var Class1 = function(a, b, c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
    var Class2 = function(d) {
        this.d = d;
    }
    
    var BridgeClass = function(a, b, c, d) {
        this.one = new Class1(a, b, c);
        this.two = new Class2(d)
    }
    

    4. 构建 XHR 连接队列

    // 获取 xhr 对象函数
    var asyncRequest = (function() {
        function handleReadyState(o, callback) {      // 其实也可以用 xhr.onreadystatechange 来实现而不用 setInterval 来监听 xhr 的 readyState
            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() {           // memoizing
                return new XMLHttpRequest;
                }
            }catch(e) {
                var msxml = [
                'MSXML2.XMLHTTP',
                'MSXML2.XMLHTTP.3.0',
                '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) {
                        continue;
                    }
                }
            }
            return http;
        };
    
        return function(method, url, callback, postData) {
            var http = getXHR();
            http.open(method, url, true);
            handleReadyState(http, callback);
            http.send(postData || null);
            return http;
        }
    })()
    
    Function.prototype.method = function(name, fn) {
        this.prototype[name] = fn;
        return this
    }
    
    
    // 实现队列
    DED.Queue = function() {
        this.queue = [];
        this.retryCount = 3;
        this.currentRetry = 0;
        this.paused = false;
        this.timeout = 5000;
        this.conn = {};
        this.timer = {};
    }
    
    DED.Queue.method('flush', function(){
        if(!this.queue.length > 0) {   // 当队列长度等于 0 时进入 if
            return;
        }
        if(this.paused) {
            this.paused = false;
            return
        }
        var that = this;
        this.currentRetry++;
    
        // 如果在规定次数内,则继续重复请求,否则结束当前该请求
        var abort = function() {
            that.conn.abort();  // 终止该请求,readyState 属性将被置为 0
            if(that.currentRetry == that.retryCount) {
                // that.onFailure.fire();
                console.log('failure: ' + that.queue[0].url)
                that.currentRetry = 0;
            } else {
                that.flush();
            }
        }
    
        var callback = function (o) {
            document.getElementById('feed-readers').innerText = o.response
            console.log(o)
    
            // 停止超时处理程序
            window.clearTimeout(that.timer);
            that.currentRetry = 0;
    
            // 剔除当前请求成功的请求项
            that.queue.shift();
            // that.onFlush.fire(o.responseText);
            if(that.queue.length == 0) {
                // that.onComplete.fire();
                return;
            }
            // 继续新的请求
            that.flush()
        }
    
        this.conn = asyncRequest(
            this.queue[0]['method'],
            this.queue[0]['url'],
            callback,
            this.queue[0]['params']
        )
        this.timer = window.setTimeout(abort, this.timeout);
    
    }).method('setRetryCount', function(count) {
        this.retryCount = count;
    }).method('setTimeout', function(time) {
        this.timeout = time;
    }).method('add', function(o) {
        this.queue.push(o);
    }).method('pause', function() {
        this.paused = true;
    }).method('dequeue', function() {
        this.queue.pop()
    }).method('clear', function() {
        this.queue = []
    })
    
    // usage
    var q = new DED.Queue;
    q.setRetryCount(3);
    q.setTimeout(1000);
    q.add({
        method: 'GET',
        'url': 'https://www.baidu.com',
    });
    q.add({
        method: 'GET',
        'url': 'https://www.baidu.com?xiaoming',
    });
    
    q.flush()
    
    // 在真实使用中,可以在添加事件的时候使用桥接函数;
    // 也可以提供一个动作调度函数,桥接用户操作所包含的输入信息并将其委托给恰当的处理代码。
    

    5. 桥接模式的利与弊

    • 利:
      • 将抽象与其实现隔离开,有助于独立地管理软件的各个部分
      • Bug更容易查找
      • 促进代码的模块化,提高抽象的灵活度
      • 可以用来把一组类和函数连接起来,而且提供了一种借助于特权函数访问私有数据的手段
    • 弊:
      • 增加了函数调用次数,对性能有一些负面影响
      • 提高了系统的复杂度
      • 不可滥用

    注意

    转载、引用,但请标明作者和原文地址

  • 相关阅读:
    EcShop二次开发学习方法
    [ 产品经理 ] 互联网产品经理常用软件及工作平台
    Tengine – Nginx衍生版
    把PHP大牛记下来,方便以后关注
    看了极光推送技术原理的几点思考
    centos磁盘满了,查找大文件并清理
    LNMP一键安装包 PHP自动升级脚本
    微信红包系统设计 & 优化
    程序员每天每周每月每年该做的事
    php中$_REQUEST、$_POST、$_GET的区别和联系小结
  • 原文地址:https://www.cnblogs.com/CccZss/p/8492303.html
Copyright © 2011-2022 走看看