摘要:橋接實現的時候橋接模式非常有用可能正是由于這個該模式使用地不夠廣泛在設計時該模式可以弱化與使用它的類和對象之間的耦合該模式的作用在于將抽象與其實現隔離開讓他們獨立變化而且對于事件驅動編程有許多好處有以及其他基于動作的方法無論它們是用來創建鼓
橋接
實現 API 的時候,橋接模式非常有用,可能正是由于這個,該模式使用地不夠廣泛.在設計 js API 時,該模式可以弱化API 與使用它的類和對象之間的耦合. 該模式的作用在于**將抽象與其實現隔離開,讓他們獨立變化**.而且對于事件驅動編程有許多好處. js API有 getter, setter, requester 以及其他基于動作的方法.無論它們是用來創建 Web 鼓舞 API 還是普通 accessor 和 mutator.在實現過程中橋接模式都有助于保持 API 代碼的簡潔.事件監聽器
最常見的應用場合之一是事件監聽回調.假設有一個 API 函數 getBeerById, 他根據一個標識符返回有關啤酒的信息.
addEvent(ele, "click", getBeerById); function getBeerById(e) { var id = this.id; asyncRequest("GET", "beer.url?id=" + id, function(resp) { // Callback response. console.log("Requested Beer: " + resp.responseText); }); }
這個 API 只能工作在瀏覽器中,根據事件監聽器回調函數的機制,事件對象自然會被作為第一個參數傳遞給這個函數,在本例中沒有使用這個參數,只是從 this 對象獲取 id.那么如果在命令行環境運行它就失效不起作用.
function getBeerById(id, callback) { // Make request for beer by ID, then return the beer data. asyncRequest("GET", "beer.url?id=" + id, function (resp) { // callback reponse callback(resp.responseText); }); } addEvent(ele, "click", getBeerByIdBridge); function getBeerByIdBridge(e) { getBeerById(this.id, function (beer) { console.log("Requested Beer: " + beer); }); }
這樣就只針對接口而不是實現進行編程,用橋接模式把抽象隔離開來.
有了這層橋接元素,API 的適用范圍大大拓寬,現在的 getBeerById 沒有和事件對象綁定在一起,可以在單元測試中運行該 API,只需提供一個 ID 和對調函數.現在可以在命令行環境運行這個接口.
除了在事件回調函數與接口之間進行橋接外,橋接模式還可以用連接公開的 API代碼和私有的實現代碼.另外,還可以連接多個類.從類的角度看,意味著把接口作為公開的代碼編寫,把類的實現作為私有代碼編寫.
可以使用一些特權方法來做橋梁以便訪問私有變量空間.第3章已經見到過.
var Public = function () { var secretNum = 3; this.privilegedGetter = function () { return secretNum; }; }; var p = new Public(); var data = p.privilegedGetter();
連接多個類:
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); }
在這里,橋接類是一個門面類,不同的是橋接模式能夠讓Class1和 Class2獨立于 BridgeClass 而發生變化,和門面類不同.
適用場合事件驅動編程必備.不過我們喜歡事件驅動開發的函數式風格,卻忘了編寫接口.判斷什么時候是用橋接模式很簡單:
$("#example-id").on("click", function () { new RichTextEditor(); })l
現在沒法看出編輯器要顯示在哪,有什么配置項,還有如何修改.要做的是讓接口"可橋接"(可適配)...
還有就是之前講到的特權函數用來訪問私有數據.
利讓 API 更強壯,提高組件的模塊化程度.把抽象和其實現隔離開,有助于獨立管理,而且Bug 更容易查找.
弊每使用一個橋接元素都要增加一次函數調用,提高系統復雜度,影響性能,不要濫用,舉例來說,如果一個橋接函數被用于連接兩個函數,但是其中某個函數根本不會在橋接函數之外被調用,那么該橋接函數可以不用.
----------next part----------
組合同一條命令在多個對象上引發復雜或者遞歸的操作.
兩大好處:
用同樣的方法處理對象集合和其中的特定子對象.組合對象 composite 和組成它的對象實現了同批操作.是一種向下傳遞的操作性質.
把一批子對象組織成樹形結構,使整棵樹都可以被遍歷.所有組合對象都實現了一個用來獲取子對象的方法.
組合對象的結構組合對象的層次體系中有兩種類型的對象:葉對象和組合對象,是一個遞歸定義:一個組合對象由一些別的組合對象和葉對象組成.只有葉對象不再包含子對象,它是組合對象中最基本的元素,也落實了各種操作.(樹是數據結構中較為基本的概念,這里的概念應該不難理解的)
使用必須同時具備兩個條件:
存在一批組織成某種層次體系的對象
希望對這批對象或者其中一部分對象進行一個共同操作.
組合模式擅長于對大批對象進行操作.組織這類對象并把操作從一個層次向下一個層次傳遞,可以弱化對象間的耦合并且可以互換的使用一些類或者實例.
要求創建一個表單,可以保存,恢復,驗證值.看似不復雜,但是主要問題在于表單中元素的內容和數目完全未知,而且因用戶而異.緊密耦合到 Name 和 Address 特定表單域的 validate 函數不會起作用,因為無法驗證哪些域...
現在是組合模式大展身手的時候,首先,我們要逐個驗證表單的各個組成元素,判斷屬于組合對象還是葉對象.表單最基本的構成要素是用戶用于輸入數據的域,由input, select,textarea 等等組成.上面一層是用于組織域的 fieldset 標簽.最頂層是表單自身.
葉對象 (input) --| | -- 組合對象 (filedset) | 葉對象 (input) --| | |=組合對象 (form) 葉對象 (select) --| | --組合對象 (fieldset) | 葉對象 (textarea)--| |
組合對象和其所有子對象都具有相同的接口,可能有人會把他們看成超類和子類的關系,但是并非如此,葉對象沒有繼承上一級組合對象.
首先是創建一個動態表單并且實現save 和 validate 操作.表單中實際擁有的域因用戶而異,所以 save,validate 函數不可能滿足每個人需要,不過可以設計一個模塊化表單,以便將來任何時候都能為其添加各種元素,不用修改 save 和 validate 函數.
不用為表單元素的每一種可能組合編寫一套方法,應該讓這兩個方法和表單域自身關聯起來.讓每個域都可以保存和驗證自己:
nameFieldset.validate(); nameFieldset.save();
難點在于如何同時在所有域上執行這些操作,使用組合模式來簡化代碼:要保存所有域,只需一次調用:topForm.save();topForm 對象將會在所有子對象上遞歸調用 save 方法,實際的 save 操作只會發生在底層的葉對象上.組合對象志氣到了一個傳遞調用的作用.
實現代碼:
首先,創建組合對象和葉對象需要實現的兩個接口:
var Composite = new Interface("Composite", ["add", "remove", "getChild"]); var FormItem = new Interface("FormItem", ["save"]);
目前 FormItem 只要求實現一個 save 函數,稍后會對其進行擴充.
CompositeForm 類的代碼如下:
var CompositeForm = function(id, method, action) { // implements Composite, Formitem this.formComponents = []; this.element = document.createElement("form"); this.element.id = id; this.element.method = method || "POST"; this.element.action = action || "#"; }; CompositeForm.prototype.add = function (child) { Interface.ensureImplements(child, Composite, FormItem); this.formComponents.push(child); this.element.appendChild(child.getElement()); }; CompositeForm.prototype.remove = function (child) { for (var i = 0, len = this.formComponents.length; i < len; i++) { if (this.formComponents[i] === child) { this.formComponents.splice(i, 1); // Remove one element from the array at position i. break; } } }; CompositeForm.prototype.getChild = function (i) { return this.formComponents[i]; }; CompositeForm.prototype.remove = function (child) { for (var i = 0, len = this.formComponents.length; i < len; i++) { this.formComponents[i].save(); } }; CompositeForm.prototype.getElement = function () { return this.element; };
CompositeForm 的子對象保存在一個數組中.使用 Interface.ensureImplements 是為了保證要添加到組合對象中的對象實現了正確的接口.
現在看看葉對象類:
var Field = function (id) { // implements Composite, FormItem this.id = id; }; Field.prototype.add = function () {}; Field.prototype.remove = function () {}; Field.prototype.getChild = function () {}; Field.prototype.save = function () { setCookie(this.id, this.getValue()); }; Field.prototype.getElement = function () { return this.element; }; Field.prototype.getValue = function () { throw new Error("Unsupported operation on the class Field."); };
這個類將被各個葉對象類繼承.它將 Composite 接口中的方法實現為空函數,因為葉節點不會有子對象.
這里最簡單地實現了 save 方法.但是把用戶原始數據放在 Cookie 是一個非常糟糕的做法.因為 Cookie 很容易被篡改,所以數據的有效性得不到保證.其次,存儲在 Cookie 中的數據有大小限制.所以用戶的數據可能不會被全部保存下來. 最后,還會影響性能,因為每次請求中 Cookie 都會作為 http 頭被一起發送.
save 方法用 getValue 方法獲得所要保存的對象值,getValue() 方法各個子類中的實現各不相同.使用 save 方法,不用提交表單也能保存表單的內容.
這個對于長表單來說很有用,因為用戶可以不用填完表單中途保存, 然后忙完其他事情再來完成表單的填寫:
var InputField = function(id, label) { // implements Composite, FormItem Field.call(this, id); this.input = document.createElement("input"); this.input.id = id; this.label = document.createElement("label"); var labelTextNode = document.createTextNode(label); this.label.appendChild(lavelTExtNode); this.element = document.createElement("div"); this.element.className = "input-field"; this.label.appendChild(this.label); this.label.appendChild(this.input); }; extend(InputField, Field); // Inherit from Field. InputField.prototype.getValue = function () { return this.input.value; };
InputField 是 Field 的子類之一.大多數方法都是從Field 繼承而來.但是他也實現了針對 input 標簽的 getValue 方法的代碼.TextareaField 和 SelectField 也實現了自己特有的 getValue 方法.
var TextareaField = function(id, label) { // implements Composite, FormItem Field.call(this, id); this.textarea = document.createElement("textarea"); this.textarea.id = id; this.label = document.createElement("label"); var labelTextNode = document.createElement("select"); this.select.id = id; this.element = document.createElement("div"); this.element.className = "input-field"; this.element.appendChild(this.label); this.element.appendChild(this.select); }; extend(SelectField, Field); // Inherit from Field. SelectField.prototype.getValue = function () { return this.select.options[this.select.selectedIndex].value; };利
使用組合模式,簡單的操作也能產生復雜的結果.不必編寫大量手工遍歷數據或者其他數據結構的粘合代碼,只需對最頂層的對象執行操作,讓每一個子對象自己傳遞這個操作.
組合模式中,各個對象之間的耦合非常松散.只要他們實現了同樣的接口,那么改變他們的位置或者互相交換很簡單.促進了代碼得寵用,也有利于代碼重構.
用組合模式組織起來的對象形成了一個出色的層次體系.每當對頂層對象執行一個操作時,實際上是在對整個結構進行深度優先搜索以查找節點.在該層次體系中添加,刪除,查找節點都很容易.
組合對象的易用性可能掩蓋了它所支持的每一種操作的代價.由于對組合對象調用的任何操作都會被傳遞到他的所有子對象,那么如果層次體系很大,系統的性能就會受到影響.topGallery.show()這樣一個方法的調用會引起一次對整個數結構的遍歷.
小結它將一批子對象組織為樹形結構,只要一條命令就可以操作樹中的所有對象.他提高了代碼的模塊化程度,而且便于代碼重構和對象的替換.這種模式特別適用于動態的 HTML 用戶界面,在他的幫助下,可以在不知道用戶界面的最終格局的情況下進行開發.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80460.html
摘要:橋接模式和裝飾模式的區別設計模式裝飾模式橋接模式和裝飾模式都是通過將繼承關系轉換為關聯關系從而減少系統中類的數量,降低系統的耦合性。裝飾器模式支持多層裝飾,通過不同的組合可以實現不同的行為。 產生橋接模式的動機: 假設這樣一種情況:我們有大中小型號的毛筆,有紅藍黑三種顏料。如果需要不同顏色,不同型號的毛筆有如下兩種設計方法: 為每一種型號的毛筆都提供三種顏料的版本。 將毛筆和顏料分開...
摘要:門面模式燜面有兩個作用一是簡化類的接口二是消除類與使用他的業務代碼之間的耦合他幾乎是所有庫的核心原則通過建立一些便利方法可以讓復雜系統變得更加簡單易用燜面模式可以使庫提供的工具更加容易理解燜面可以簡化錯誤記錄或者跟蹤頁面視圖統計數據這類這類 門面模式 燜面,有兩個作用,一是簡化類的接口;二是消除類與使用他的業務代碼之間的耦合.他幾乎是所有 JS 庫的核心原則.通過建立一些便利方法可以讓...
摘要:橋接模式概述橋接模式將抽象部分與它的實現部分分離,使他們都可以獨立地變化。實現使用發送信息的例子來實現橋接模式。橋接模式也從側面體現了使用對象組合的方式比繼承要來得更靈活。代碼實現橋接模式 橋接模式 概述 橋接模式將抽象部分與它的實現部分分離,使他們都可以獨立地變化。通俗地說,橋接就是在不同的東西之間搭一個橋,讓它們能夠連接起來,可以相互通訊和使用。在橋接模式中的橋接是在被分離的抽象部...
摘要:橋接模式橋接是用于把抽象化與現實化解耦,使得二者可以獨立變化,這種類型的設計模式屬于結構型模式,它通過提供抽象化和現實化之間的橋接結構,實現二者的解耦。所以接口和實現是可以組合的,這種組合我們稱之為橋接模式。主要用在系統開始設計的時候使用。 橋接模式 橋接(Bridge)是用于把抽象化與現實化解耦,使得二者可以獨立變化,這種類型的設計模式屬于結構型模式,它通過提供抽象化和現實化之間的橋...
閱讀 2314·2021-11-08 13:13
閱讀 1245·2021-10-09 09:41
閱讀 1683·2021-09-02 15:40
閱讀 3186·2021-08-17 10:13
閱讀 2546·2019-08-29 16:33
閱讀 3122·2019-08-29 13:17
閱讀 3131·2019-08-29 11:00
閱讀 3295·2019-08-26 13:40