资讯专栏INFORMATION COLUMN

[设计模式][适配器模式][Javascript]

genedna / 484人阅读

摘要:定义适配器模式的目标是改变接口,是将一组接口适配成用户期待的接口。当引用的外部库的发生改变的时候,如何适合这种改变如何改变对象和类的接口,使之能够为现在的系统所兼容,这就是适配器模式的意义。

  

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

定义

适配器模式的目标是改变接口,是将一组接口适配成用户期待的接口。
当引用的外部库的API发生改变的时候,如何适合这种改变?如何改变对象和类的接口,使之能够为现在的系统所兼容,这就是适配器模式的意义。

简单的来说,可以通过对象传入,然后做委托来实现。但是其实可以在做委托的过程中做更多的工作来丰富适配器本身

需求

有一个数据模型DataModel,它的来源可能是不同的数据库,MySQL/MongoDB等等。DataModel有一组CURD的接口,来读写数据库。
需求是可以适配不同的数据库来进行数据的读写。

这里扯出来说一说。在.net里面有一个ADO.NET,就是为数据库的访问提供多个统一的接口和基类就是DataAdapter,用来连接DataSet与Database。
有兴趣可以看一下:http://msdn.microsoft.com/zh-cn/library/h43ks021(v=vs.110).aspx

类图

前端的数据库,额,不能说数据库吗,就说能存存东西的地方:LocalStorage和IndexDB。
LocalStorage就不说了,这个比较大众了,twitter还因为LocalStorage爆出过XSS攻击的问题

关于IndexDB的知识,UML图没有给的很清楚,参考这里:

https://developer.mozilla.org/zh-CN/docs/IndexedDB

http://code.tutsplus.com/tutorials/working-with-indexeddb--net-34673

这里用LocalStorage来做例子,而且会模仿redis加入一个时间戳,未来可以用来标记是否数据过期

适配器模式这里仔细说一下,在传统的实现中,适配器模式有两种实现方式:类适配器模式和对象适配器模式

对象适配就是这里给出的例子,在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();
参考

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87602.html

相关文章

  • JavaScript 设计模式(四):适配模式

    摘要:与其它模式的异同适配器模式不会改变原有接口,这一点与装饰者模式和代理模式类似。代理模式适配器模式与代理模式最相似,同样都是创建一个新对象包装一次,实现对本体的调用。外观模式外观模式与适配器模式最大的区别,是定义了一个新的接口。 showImg(https://segmentfault.com/img/bVbul8d?w=800&h=600); 适配器模式:将一个类(对象)的接口(方法或...

    MingjunYang 评论0 收藏0
  • JavaScript设计模式系列五:配器模式

    摘要:什么是适配器模式所谓适配器模式就是用一个新的接口对现有的接口进行包装,处理类与的不匹配。对象适配器可以适配它的父对象接口方法或属性。装饰者模式增强了对象的功能而同时又不改变它的接口,因此它对程序的透明度比适配器要好。 什么是适配器模式 所谓 适配器模式 就是用一个新的接口对现有的接口进行包装,处理类与API的不匹配。使用这种模式的对象又叫作包装器。比如我们有一个接口: function...

    banana_pi 评论0 收藏0
  • 从ES6重新认识JavaScript设计模式(四): 配器模式

    摘要:什么是适配器模式适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。中的适配器模式在前端项目中,适配器模式的使用场景一般有以下三种情况库的适配参数的适配和数据的适配。 1 什么是适配器模式 适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 在...

    URLOS 评论0 收藏0
  • JavaScript设计模式配器模式

    摘要:旧接口格式和使用者不兼容,中间加一个适配器转换接口。模式作用使用一个已经存在的对象,但其方法或接口不符合你的要求。 原文博客地址:https://finget.github.io/2018/11/22/adapter/ 适配器模式 适配器模式(Adapter)是将一个类(对象)的接口(方法或属性)转换成客户希望的另外一个接口(方法或属性),适配器模式使得原本由于接口不兼容而不能一起工作...

    CNZPH 评论0 收藏0
  • JavaScript 设计模式读书笔记(七)——配器模式

    摘要:与门面模式的联系本文要说的适配器模式和上一篇门面模式在思想上有相似之处,所以放在一起说。我们以中的一个为例,说说实际应用中的适配器模式的使用方法。而如果实现层的问题不大,要解决一部分适配问题的话,适配器模式就是很好的选择了。 与门面模式的联系 本文要说的适配器模式和上一篇门面模式在思想上有相似之处,所以放在一起说。它们都对类的接口进行了一些改变。门面模式是把相似的或是完成相关任务的接...

    AZmake 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<