摘要:定義適配器模式的目標(biāo)是改變接口,是將一組接口適配成用戶期待的接口。當(dāng)引用的外部庫(kù)的發(fā)生改變的時(shí)候,如何適合這種改變?nèi)绾胃淖儗?duì)象和類的接口,使之能夠?yàn)楝F(xiàn)在的系統(tǒng)所兼容,這就是適配器模式的意義。
定義The Adapter Pattern is a software design pattern that allows the interface of an existing class to be used from another interface. It"s often used to mak existing classes work with others without modifying their source code.
From http://en.wikipedia.org/wiki/Adapter_pattern
適配器模式的目標(biāo)是改變接口,是將一組接口適配成用戶期待的接口。
當(dāng)引用的外部庫(kù)的API發(fā)生改變的時(shí)候,如何適合這種改變?如何改變對(duì)象和類的接口,使之能夠?yàn)楝F(xiàn)在的系統(tǒng)所兼容,這就是適配器模式的意義。
簡(jiǎn)單的來(lái)說(shuō),可以通過(guò)對(duì)象傳入,然后做委托來(lái)實(shí)現(xiàn)。但是其實(shí)可以在做委托的過(guò)程中做更多的工作來(lái)豐富適配器本身
需求有一個(gè)數(shù)據(jù)模型DataModel,它的來(lái)源可能是不同的數(shù)據(jù)庫(kù),MySQL/MongoDB等等。DataModel有一組CURD的接口,來(lái)讀寫數(shù)據(jù)庫(kù)。
需求是可以適配不同的數(shù)據(jù)庫(kù)來(lái)進(jìn)行數(shù)據(jù)的讀寫。
這里扯出來(lái)說(shuō)一說(shuō)。在.net里面有一個(gè)ADO.NET,就是為數(shù)據(jù)庫(kù)的訪問(wèn)提供多個(gè)統(tǒng)一的接口和基類就是DataAdapter,用來(lái)連接DataSet與Database。
有興趣可以看一下:http://msdn.microsoft.com/zh-cn/library/h43ks021(v=vs.110).aspx
前端的數(shù)據(jù)庫(kù),額,不能說(shuō)數(shù)據(jù)庫(kù)嗎,就說(shuō)能存存東西的地方:LocalStorage和IndexDB。
LocalStorage就不說(shuō)了,這個(gè)比較大眾了,twitter還因?yàn)長(zhǎng)ocalStorage爆出過(guò)XSS攻擊的問(wèn)題
關(guān)于IndexDB的知識(shí),UML圖沒(méi)有給的很清楚,參考這里:
https://developer.mozilla.org/zh-CN/docs/IndexedDB
http://code.tutsplus.com/tutorials/working-with-indexeddb--net-34673
這里用LocalStorage來(lái)做例子,而且會(huì)模仿redis加入一個(gè)時(shí)間戳,未來(lái)可以用來(lái)標(biāo)記是否數(shù)據(jù)過(guò)期
適配器模式這里仔細(xì)說(shuō)一下,在傳統(tǒng)的實(shí)現(xiàn)中,適配器模式有兩種實(shí)現(xiàn)方式:類適配器模式和對(duì)象適配器模式
對(duì)象適配就是這里給出的例子,在adapter中含有adaptee的實(shí)例,然后再調(diào)用
類適配需要繼承adaptee和adapter,然后內(nèi)部做接口適配,這個(gè)需要用多繼承,不建議在javascript中使用
角色AbstractDataAdapter (Target) 系統(tǒng)適應(yīng)的接口組
LsDataAdapter (Adapter) 適配器 負(fù)責(zé)接口轉(zhuǎn)換
LsDataAdaptee (Adaptee)
實(shí)現(xiàn)var prototype = require("prototype"); var AbstractDataAdapter = prototype.Class.create({ create: function(key, data) { throw new Error("method must be override!"); }, update: function(key, olddata, newdata) { throw new Error("method must be override!"); }, read: function(key) { throw new Error("method must be override!"); }, delete: function(key) { throw new Error("method must be override!"); } }); var LsAdaptee = function () { // @todo 模擬判斷是nodejs環(huán)境還是瀏覽器環(huán)境 if (require) { var info = {}; return { removeItem: function (key) { return delete info[key]; }, setItem: function (key, data) { console.log("setItem -- key:"+key+", data:"+data) return info[key] = data }, getItem: function (key) { console.log("getItem -- key:"+key+", data:"+info[key]) return info[key] } } }else{ return window.localStorage; } } var LsDataAdapter = prototype.Class.create(AbstractDataAdapter, { initialize: function(options) { this.adaptee = new LsAdaptee(); }, create: function(key, data) { var already = this.adaptee.getItem(key); if (already) { return false; } if (data) { var insert = { data: data, jointime: Date.now() } this.adaptee.setItem(key, JSON.stringify(insert)); return true; }else{ return false; } }, update: function(key, olddata, newdata) { if (newdata) { var insert = { data: newdata, jointime: Date.now() } } this.adaptee.setItem(key, JSON.stringify(insert)); }, read: function(key) { var data = this.adaptee.getItem(key); if (data) { var info = JSON.parse(data); return info.data; }else{ return false; } }, delete: function(key) { this.adaptee.remove(key); }, parse: function(source) { // @todo 將datamodel轉(zhuǎn)為viewmodel return source; } }); var Model = prototype.Class.create({ initialize: function(options) { this.adapter = options.adapter; this.data = {}; }, set: function(key, data) { this.data[key] = data; this.adapter.update(key, null, data); }, get: function(key) { return this.data[key] = this.adapter.read(key); } }) var Main = function () { var lsDataAdapter = new LsDataAdapter(); var model = new Model({ adapter: lsDataAdapter}); model.set("USER_INFO", {TOKEN: "a627991dd0e5441be9fdd6f88746148a"}); var data = model.get("USER_INFO", {TOKEN: "a627991dd0e5441be9fdd6f88746148a"}); console.log("---------------------------") console.log(data); } Main();參考
http://sourcemaking.com/design_patterns/adapter
http://blog.csdn.net/hguisu/article/details/7527842
http://www.cnblogs.com/Terrylee/archive/2006/02/18/333000.html
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/87602.html
摘要:與其它模式的異同適配器模式不會(huì)改變?cè)薪涌?,這一點(diǎn)與裝飾者模式和代理模式類似。代理模式適配器模式與代理模式最相似,同樣都是創(chuàng)建一個(gè)新對(duì)象包裝一次,實(shí)現(xiàn)對(duì)本體的調(diào)用。外觀模式外觀模式與適配器模式最大的區(qū)別,是定義了一個(gè)新的接口。 showImg(https://segmentfault.com/img/bVbul8d?w=800&h=600); 適配器模式:將一個(gè)類(對(duì)象)的接口(方法或...
摘要:什么是適配器模式所謂適配器模式就是用一個(gè)新的接口對(duì)現(xiàn)有的接口進(jìn)行包裝,處理類與的不匹配。對(duì)象適配器可以適配它的父對(duì)象接口方法或?qū)傩浴Qb飾者模式增強(qiáng)了對(duì)象的功能而同時(shí)又不改變它的接口,因此它對(duì)程序的透明度比適配器要好。 什么是適配器模式 所謂 適配器模式 就是用一個(gè)新的接口對(duì)現(xiàn)有的接口進(jìn)行包裝,處理類與API的不匹配。使用這種模式的對(duì)象又叫作包裝器。比如我們有一個(gè)接口: function...
摘要:什么是適配器模式適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口,使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。中的適配器模式在前端項(xiàng)目中,適配器模式的使用場(chǎng)景一般有以下三種情況庫(kù)的適配參數(shù)的適配和數(shù)據(jù)的適配。 1 什么是適配器模式 適配器模式(Adapter):將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口,使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。 在...
摘要:舊接口格式和使用者不兼容,中間加一個(gè)適配器轉(zhuǎn)換接口。模式作用使用一個(gè)已經(jīng)存在的對(duì)象,但其方法或接口不符合你的要求。 原文博客地址:https://finget.github.io/2018/11/22/adapter/ 適配器模式 適配器模式(Adapter)是將一個(gè)類(對(duì)象)的接口(方法或?qū)傩?轉(zhuǎn)換成客戶希望的另外一個(gè)接口(方法或?qū)傩?,適配器模式使得原本由于接口不兼容而不能一起工作...
摘要:與門面模式的聯(lián)系本文要說(shuō)的適配器模式和上一篇門面模式在思想上有相似之處,所以放在一起說(shuō)。我們以中的一個(gè)為例,說(shuō)說(shuō)實(shí)際應(yīng)用中的適配器模式的使用方法。而如果實(shí)現(xiàn)層的問(wèn)題不大,要解決一部分適配問(wèn)題的話,適配器模式就是很好的選擇了。 與門面模式的聯(lián)系 本文要說(shuō)的適配器模式和上一篇門面模式在思想上有相似之處,所以放在一起說(shuō)。它們都對(duì)類的接口進(jìn)行了一些改變。門面模式是把相似的或是完成相關(guān)任務(wù)的接...
閱讀 3405·2021-11-08 13:12
閱讀 2934·2021-10-15 09:41
閱讀 1571·2021-10-08 10:05
閱讀 3431·2021-10-08 10:04
閱讀 2281·2021-09-29 09:34
閱讀 2643·2019-08-30 15:55
閱讀 3059·2019-08-30 15:45
閱讀 2714·2019-08-29 14:17