1. 程式人生 > >JavaScript設計模式(4)

JavaScript設計模式(4)

元素 end java 監聽器 post text HR ole abort

橋接模式

在設計一個 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更容易查找
    • 促進代碼的模塊化,提高抽象的靈活度
    • 可以用來把一組類和函數連接起來,而且提供了一種借助於特權函數訪問私有數據的手段
  • 弊:
    • 增加了函數調用次數,對性能有一些負面影響
    • 提高了系統的復雜度
    • 不可濫用

註意

轉載、引用,但請標明作者和原文地址

JavaScript設計模式(4)