[設計模式][適配器模式][Javascript]

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_patternjavascript

定義

適配器模式的目標是改變接口,是將一組接口適配成用戶期待的接口。
當引用的外部庫的API發生改變的時候,如何適合這種改變?如何改變對象和類的接口,使之可以爲如今的系統所兼容,這就是適配器模式的意義。html

簡單的來講,能夠經過對象傳入,而後作委託來實現。可是其實能夠在作委託的過程當中作更多的工做來豐富適配器自己前端

需求

請輸入圖片描述

有一個數據模型DataModel,它的來源多是不一樣的數據庫,MySQL/MongoDB等等。DataModel有一組CURD的接口,來讀寫數據庫。
需求是能夠適配不一樣的數據庫來進行數據的讀寫。java

這裏扯出來講一說。在.net裏面有一個ADO.NET,就是爲數據庫的訪問提供多個統一的接口和基類就是DataAdapter,用來鏈接DataSet與Database。
有興趣能夠看一下:http://msdn.microsoft.com/zh-cn/library/h43ks021(v=vs.110).aspxnode

類圖

請輸入圖片描述

前端的數據庫,額,不能說數據庫嗎,就說能存存東西的地方:LocalStorage和IndexDB。
LocalStorage就不說了,這個比較大衆了,twitter還由於LocalStorage爆出過XSS攻擊的問題redis

關於IndexDB的知識,UML圖沒有給的很清楚,參考這裏:數據庫

這裏用LocalStorage來作例子,並且會模仿redis加入一個時間戳,將來能夠用來標記是否數據過時segmentfault

適配器模式這裏仔細說一下,在傳統的實現中,適配器模式有兩種實現方式:類適配器模式和對象適配器模式瀏覽器

  • 對象適配就是這裏給出的例子,在adapter中含有adaptee的實例,而後再調用
  • 類適配須要繼承adaptee和adapter,而後內部作接口適配,這個須要用多繼承,不建議在javascript中使用

角色

  • AbstractDataAdapter (Target) 系統適應的接口組
  • LsDataAdapter (Adapter) 適配器 負責接口轉換
  • LsDataAdaptee (Adaptee)

實現

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環境仍是瀏覽器環境
  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轉爲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();

參考

相關文章
相關標籤/搜索