[设计模式][适配器模式][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();

参考

相关文章
相关标签/搜索