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 ...
随机推荐
- JS判断值是否是正数
1.使用isNaN()函数 isNaN()的缺点就在于 null.空格以及空串会被按照0来处理 NaN: Not a Number /** *判断是否是数字 * **/ function isReal ...
- TagHelper的一些个人学习体会(发现了微软官方文档的一个错误)
最近一直在学习.net core 上周六开始学习Taghelper的自定义,准备周日写个博客和大家分享一下学习体会,无奈周日去考科四了,回来之后就感冒了,现在还没好.可是我发现了微软官方文档的一个错误 ...
- 简谈-Python的输入、输出、运算符、数据类型转换
输出: 格式化输出: 看到了 % 这样的操作符,这就是Python中格式化输出. 换行输出: 在输出的时候,如果有 \n 那么,此时 \n 后的内容会在另外一行显示 输入: 在python2.7当中, ...
- pdo操纵mysql数据库
PDO是mysql数据库操作的一个公用类了,我们不需要进行自定类就可以直接使用pdo来操作数据库了,但是在php默认配置中pdo是未开启所以我们必须先在php.ini中开启它才可以使用,下文我会讲到. ...
- 使用 rsync 同步
原文地址 http://www.howtocn.org/rsync:use_rsync 选项 说明 -a, ––archive 归档模式,表示以递归方式传输文件,并保持所有文件属性,等价于 -rlpt ...
- SOA与基于CDIF的API的联动
几千年来,巴别塔的故事一直是人类面对的一个核心的困境.为了交流和沟通我们人类创造出语言,但沟通与交流仍然存在障碍……相同语言之间的沟通依语境的不同,尚且存在巨大的鸿沟,不同语言之间更是让人坐困愁城. ...
- css浮动布局,浮动原理,清除(闭合)浮动方法
css浮动 1.什么是浮动:在我们布局的时用到的一种技术,能够方便我们进行布局,通过让元素浮动,我们可以使元素在水平上左右移动,再通过margin属性调整位置 2.浮动的原理:使当前元素脱离普通流,相 ...
- 关于BSTR和SysStringLen方法的简单研究
英文的我编不下去了,所以还是先写个中文的吧, 之前遇到了SysStringLen求Bstr长度不正确的问题,试验了几次都不行的情况下我觉得可能是这个方法的bug,所以就没管. 大概的情况是这样: in ...
- Java中的锁分类
在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分段锁 偏向锁/轻量级 ...
- poj1847 Tram 最短路Dijkstra
题目链接:http://poj.org/problem?id=1847 Dijkstra算法的模版应用 题意:给你N个点和起点终点,点与点有铁路,接下来的N行分别为点i的情况 第一个数字表示与该点连通 ...