javaScript 设计模式系列之二:适配器模式
介绍
适配器模式将一个类的接口转接成用户所期待的,有助于避免大规模改写现有客户代码。
In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used from another interface. It is often used to make existing classes work with others without modifying their source code.
例:电源转换器,我们国家的电器使用普通的扁平两项或三项插头,而去外国的话,使用的标准就不一样了,比如德国,使用的是德国标准,是两项圆头的插头。如果去德国旅游,那么我们使用的手机充电器插头无法插到德国的插排中去,那就意味着我们无法给手机充电。怎样解决这个问题呢?只要使用一个电源转化器就行了。
例子:购物车
Shopping Cart Example with Local Storage
function ShoppingCart() {}
ShoppingCart.prototype.add = function(item) {
var items = localStorage.getItem('cart');
if (items) {
items = JSON.parse(items);
if (items[item.id]) {
items[item.id].quantity += 1;
} else {
item.quantity = 1;
items[item.id] = item;
}
} else {
items = {};
item.quantity = 1;
items[item.id] = item;
}
items = JSON.stringify(items);
localStorage.setItem('cart', items);
return item;
};
var cart = new ShoppingCart();
cart.add({ id: 1, product: 'movie 1' }); // quantity is 1 for product 1
cart.add({ id: 2, product: 'movie 2' }); // quantity is 1 for product 2
cart.add({ id: 1, product: 'movie 1' }); // quantity is 2 for product 1
上面代码中通过 localStorage 存储购物车的数据。若此时改变需求,需要通过服务器端存储,这时你不得不改变现有的代码,此时更好的实现方式时引入"适配器"。
Shopping Cart Example with Adapters
// jQuery deferreds and promises
var localStorageAdapter = {
findAll: function() {
var deferred = new $.Deferred();
var items = localStorage.getItem('cart');
if (items) {
items = JSON.parse(items);
}
deferred.resolve(items);
return deferred.promise();
},
save: function(items) {
var deferred = new $.Deferred();
items = JSON.stringify(items);
localStorage.setItem('cart', items);
deferred.resolve();
return deferred.promise();
}
};
// jQuery deferreds and promises.
var serverSideAdapter = {
findAll: function() {
return $.ajax({
url: '/shopping-cart'
}).then(function(response) {
return response.items;
});
},
save: function(items) {
return $.ajax({
url: '/shopping-cart',
type: 'post',
data: {
items: items
}
});
}
};
function ShoppingCart(adapter) {
this.adapter = adapter;
}
ShoppingCart.prototype.add = function(item) {
var adapter = this.adapter;
var deferred = new $.Deferred();
adapter.findAll().then(function(items) {
if (items) {
if (items[item.id]) {
items[item.id].quantity += 1;
} else {
item.quantity = 1;
items[item.id] = item;
}
} else {
items = {};
item.quantity = 1;
items[item.id] = item;
}
adapter.save(items).then(function() {
deferred.resolve(item);
});
});
return deferred.promise();
};
// localStorageAdapter
var cart = new ShoppingCart(localStorageAdapter);
cart.add({ id: 1, product: 'movie 1' }).then(function(item) { }); // quantity is 1 for product 1
cart.add({ id: 2, product: 'movie 2' }).then(function(item) { }); // quantity is 1 for product 2
cart.add({ id: 1, product: 'movie 1' }).then(function(item) { }); // quantity is 2 for product 1
// serverSideAdapter
var cart = new ShoppingCart(serverSideAdapter);
例子:日志记录
// 当前 logger
function BadLogger(name) {
this.name = name;
var LOG_HEADER = '[' + name + ']:';
var self = this;
return {
getName: function getName() {
return self.name;
},
getType: function getType() {
return 'BadLogger';
},
information: function information(message) {
console.info(LOG_HEADER + message + '- INFORMATION' );
},
debg: function debg(message) {
console.log(LOG_HEADER + message + '- DEBG');
},
w: function w(message) { // w stands for warning.
console.warn(LOG_HEADER + message + '- W' );
},
err: function err(message) {
console.error(LOG_HEADER + message+ '- ERR' );
}
}
}
module.exports = {
getLogger: BadLogger
}
// 另一个 logger
function ShortLogger(name) {
this.name = name;
var LOG_HEADER = '[' + name + ']';
var self = this;
var getTime = function() {
return '[' + new Date().toISOString() + ']';
}
return {
getName: function getName() {
return self.name;
},
getType: function getType() {
return 'ShortLogger';
},
i: function i(message) {
console.info(LOG_HEADER + getTime() + '[I]: ' + message);
},
d: function d(message) {
console.log(LOG_HEADER + getTime() + '[D]: ' + message);
},
w: function w(message) {
console.warn(LOG_HEADER + getTime() + '[W]: ' + message);
},
e: function e(message) {
console.error(LOG_HEADER + getTime() + '[E]: ' + message);
}
}
}
module.exports = {
getLogger: ShortLogger
}
var ShortLogger = require('./ShortLogger');
var BadLogger = require('./BadLogger');
function LoggerAdapter(loggerObj) {
if (!loggerObj) {
throw Error('Parameter [loggerObj] is not defined.');
}
console.log('[LoggerAdapter] is using Logger with name: ' + loggerObj.getName());
var CONSTANTS = {
DEBUG: 'DEBUG',
WARNING: 'WARNING',
INFORMATION: 'INFORMATION',
ERROR: 'ERROR',
BAD_LOGGER: 'BadLogger',
SHORT_LOGGER: 'ShortLogger'
};
var loggerFunctionMapper = {};
if(loggerObj.getType() === CONSTANTS.BAD_LOGGER) {
loggerFunctionMapper[CONSTANTS.DEBUG] = loggerObj.debg;
loggerFunctionMapper[CONSTANTS.INFORMATION] = loggerObj.information;
loggerFunctionMapper[CONSTANTS.WARNING] = loggerObj.w;
loggerFunctionMapper[CONSTANTS.ERROR] = loggerObj.err;
}
else if (loggerObj.getType() === CONSTANTS.SHORT_LOGGER) {
loggerFunctionMapper[CONSTANTS.DEBUG] = loggerObj.d;
loggerFunctionMapper[CONSTANTS.INFORMATION] = loggerObj.i;
loggerFunctionMapper[CONSTANTS.WARNING] = loggerObj.w;
loggerFunctionMapper[CONSTANTS.ERROR] = loggerObj.e;
}
function information(message) {
try {
loggerFunctionMapper[CONSTANTS.INFORMATION](message);
}
catch(err) {
throw Error('No implementation for Logger: ' + loggerObj.toString());
}
};
function debug(message) {
try {
loggerFunctionMapper[CONSTANTS.DEBUG](message);
}
catch(err) {
throw Error('No implementation for Logger: ' + loggerObj.toString());
}
};
...
return {
debug: debug,
information: information,
warning: warning,
error: error
}
}
module.exports = {
LoggerAdapter: LoggerAdapter
}
var ShortLogger = require('./ShortLogger');
var BadLogger = require('./BadLogger');
var LoggerAdapter = require('./LoggerAdapter');
var shortLog = ShortLogger.getLogger('ShortLoger');
var badLogger = BadLogger.getLogger('BadLogger');
var loggerAdapter = LoggerAdapter.LoggerAdapter(badLogger);
loggerAdapter.information('This is logged through LoggerAdapter');
loggerAdapter.debug('This is logged through LoggerAdapter');
loggerAdapter.warning('This is logged through LoggerAdapter');
loggerAdapter.error('This is logged through LoggerAdapter');
console.log();
var loggerAdapter2 = LoggerAdapter.LoggerAdapter(shortLog);
loggerAdapter2.information('Now This is logged through LoggerAdapter');
loggerAdapter2.debug('Now This is logged through LoggerAdapter');
loggerAdapter2.warning('Now This is logged through LoggerAdapter');
loggerAdapter2.error('Now This is logged through LoggerAdapter');
相关阅读
The Adapter Pattern in JavaScript
Design Patterns - The Adapter Pattern in JavaScript
javaScript 设计模式系列之二:适配器模式的更多相关文章
- javascript设计模式系列
javascript设计模式系列 创建型: 1.抽象工厂模式(Abstract Factory) 2.构建者模式(Builder) 3.工厂方法模式(Factory Method) 4.原型模式( ...
- Java 设计模式系列(二二)责任链模式
Java 设计模式系列(二二)责任链模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求 ...
- Java 设计模式系列(二十)状态模式
Java 设计模式系列(二十)状态模式 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式.状态模式允许一个对象在其内部状态改变的时候改 ...
- Javascript设计模式系列二
创建对象的基本模式,一.门户大开型,二.采用下划线来表示属性和方法的私用性,三.使用闭包来创建私用的成员. 一.门户大开型.只能提供公用成员.所有属性和方法都公开的.可访问的.这些共用属性都要使用th ...
- 【JavaScript设计模式系列---开篇预览】
转:http://www.cnblogs.com/Darren_code/archive/2011/08/31/JavascripDesignPatterns.html 2011-08-31 23:5 ...
- Javascript设计模式系列三
继承,一个类或对象继承另一个类或对象的三种方法.类式继承.原型式继承.掺元类. 一.类式继承,原型链.Extend函数. <script type="text/javascript&q ...
- Javascript设计模式系列一
定义类,方法赋值给prototype属性各种写法: 方法一: <script type="text/javascript"> ////定义Message类 var Me ...
- JavaScript设计模式基础(二)
JavaScript 设计模式基础(一) 原型模式 在以类为中心的面向对象编程语言中,类和对象的关系就像铸模和铸件的关系,对象总是从类中创建.而原型编程中,类不是必须的,对象未必从类中创建而来,可以拷 ...
- javascript设计模式系列二-封装
JavaScript封装: var Book = function (id, name, price) { this.id = id, this.name = name, this.price = p ...
随机推荐
- Linux - 进程调度算法
进程调度: 无论是在批处理系统还是分时系统中,用户进程数一般都多于处理机数.这将导致它们互相争夺处理机.另外,系统进程也同样需要使用处理机. 这就要求进程调度程序按一定的策略,动态地把处理机分配给处于 ...
- DbVisualizer:Oracle触发器,解决ORA-04098: 触发器 'USER.DECTUSERTEST_TRI' 无效且未通过重新验证
我没有用orcal的管理工具,而是用的DbVisualizer 9.5.2,管理数据库. 场景:需要在oracle里面实在自增字段,在网上一搜一堆文档,然后自己就找了一段自己写如下: drop tab ...
- python字符串实战
haproxy配置文件 思路:读一行,写一行 global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 info defa ...
- Vmware Vsphere WebService之vijava 开发一-vcenter连接、及集群信息获取
开始是通过java代码调用vsphere提供的原始接口,从而控制vcenter的操作.当第一个版本做完之后发现代码执行的速度特别慢,后来在网上看到有人用vijava(对vsphere原始接口封装)编程 ...
- JS模式--状态模式(状态机)
下面的状态机选择通过Function.prototype.call方法直接把请求委托给某个字面量对象来执行. var light = function () { this.currstate = FS ...
- Mongo汇总问题
1. 数据 /* 5 */ { "_id" : ObjectId("5902f7ca2b3fe442d60a0946"), "code" : ...
- Angular杂谈系列2-Angular2升级Angular4指南
什么什么?Angualr4都发布了,之前不都才Angualr2的么?又要推翻重来,啊? 那当然不是,Angualr4只是一个版本号而已,本质上还是Angular2:以后,谷歌把新版本的Angualr称 ...
- bzoj4818 [Sdoi2017]序列计数
Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望,这n个数中,至少有一个数是质数.Alice想知道,有多少个序 ...
- PHP环境搭建之PHPstorm9+PHP5开发环境配置
以前写过一篇zend studio+WAMP的:点这里,个人感觉写得不怎么好可是阅读数却上千了... 不过笔者身边好多人开始用PHPStrom了,所以就简单的写个教程 一.下载安装 PHPStrom下 ...
- hadoop单机环境搭建
[在此处输入文章标题] Hadoop单机搭建 1. 工具准备 1) Hadoop Linux安装包 2) VMware虚拟机 3) Java Linux安装包 4) Window 电脑一台 2. 开始 ...