介绍

适配器模式将一个类的接口转接成用户所期待的,有助于避免大规模改写现有客户代码。

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 设计模式系列之二:适配器模式的更多相关文章

  1. javascript设计模式系列

    javascript设计模式系列   创建型: 1.抽象工厂模式(Abstract Factory) 2.构建者模式(Builder) 3.工厂方法模式(Factory Method) 4.原型模式( ...

  2. Java 设计模式系列(二二)责任链模式

    Java 设计模式系列(二二)责任链模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求 ...

  3. Java 设计模式系列(二十)状态模式

    Java 设计模式系列(二十)状态模式 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式.状态模式允许一个对象在其内部状态改变的时候改 ...

  4. Javascript设计模式系列二

    创建对象的基本模式,一.门户大开型,二.采用下划线来表示属性和方法的私用性,三.使用闭包来创建私用的成员. 一.门户大开型.只能提供公用成员.所有属性和方法都公开的.可访问的.这些共用属性都要使用th ...

  5. 【JavaScript设计模式系列---开篇预览】

    转:http://www.cnblogs.com/Darren_code/archive/2011/08/31/JavascripDesignPatterns.html 2011-08-31 23:5 ...

  6. Javascript设计模式系列三

    继承,一个类或对象继承另一个类或对象的三种方法.类式继承.原型式继承.掺元类. 一.类式继承,原型链.Extend函数. <script type="text/javascript&q ...

  7. Javascript设计模式系列一

    定义类,方法赋值给prototype属性各种写法: 方法一: <script type="text/javascript"> ////定义Message类 var Me ...

  8. JavaScript设计模式基础(二)

    JavaScript 设计模式基础(一) 原型模式 在以类为中心的面向对象编程语言中,类和对象的关系就像铸模和铸件的关系,对象总是从类中创建.而原型编程中,类不是必须的,对象未必从类中创建而来,可以拷 ...

  9. javascript设计模式系列二-封装

    JavaScript封装: var Book = function (id, name, price) { this.id = id, this.name = name, this.price = p ...

随机推荐

  1. Linux轻松使用vim

    VIM命令---Vi IMproved, a programmers text editor文本编辑 1>gedit   图形文本编辑工具 2>vim      字符界面的编辑工具 写脚本 ...

  2. 腾讯AlloyTeam正式发布Canvas魔幻线条 - curvejs

    [原文链接] ## 写在前面 curvejs 中文读["克js"],是腾讯AlloyTeam打造的一款魔幻线条框架,让线条成为一名优秀的舞者,让线条们成为优秀的舞团,HTML5 ...

  3. Python数据处理——numpy_1

    python中数据处理最基础的一个包--numpy.它能很好的进行数据准备,类似与R语言中的数据框(DataFrame)一样.今天,就来从最基础的开始学习. import numpy as npdat ...

  4. qt中字符串转换

    11.各种数据类型的相互转换char * 与 const char *的转换char *ch1="hello11";const char *ch2="hello22&qu ...

  5. php-fpm死机解决办法,脚本后台自动重启

    本人用nginx+php7搭建了一台服务器,因为请求量太大,而且php里面又有挂起的任务,导致php-fpm在高峰期的时候经常死掉,吧php-fpm的最大进程数已经改到1000了,还是吃不消,cpu也 ...

  6. 虚拟机下安装ubuntu系统

    前期准备工具; 1,Oracle VM VirtualBox虚拟机 下载地址:http://pan.baidu.com/s/1miSaGvm 密码:c3dy 2,ubuntu系统文件 下载地址:htt ...

  7. Java中的WebService服务

    一.在本地发布一个webservice服务 1.使用jdk中的 javax.xml.ws.Endpoint 类的 static Endpointpublish(Stringaddress,Object ...

  8. openwrt通过libcurl上传图片,服务器端通过PHP接收文件

    一.客户端文件上传 libcurl上传文件有两种方式: 1.直接上传文件,类似form表单<input type=”file” />,<form enctype=”multipart ...

  9. Play学习 - 体验网页模板

    在经过无数个尝试后,最终用sbt把play所依赖的所有包都下载下来了,现在可以非常快速编译运行了.今天体验了下网页模板,觉得非常不错,在这里做个简单的介绍. 原文说明: A Play Scala te ...

  10. python 基础之pickle 与json 报错问题解决方案

    Python 基础之pickle与json 有没有在搞pickle与json在进行数据储存的时候老是报错,这个有些让人烦恼,在之前有一篇介绍过它们的基本用法以及在使用过长中避免一些坑,但是今天在把对象 ...