介绍

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

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. Elasticsearch高级搜索排序( 中文+拼音+首字母+简繁转换+特殊符号过滤)

    一.先摆需求: 1.中文搜索.英文搜索.中英混搜   如:"南京东路","cafe 南京东路店" 2.全拼搜索.首字母搜索.中文+全拼.中文+首字母混搜   如 ...

  2. 对GPIO_Init(GPIOx,&GPIO_InitStructure)的理解

    今天学习stm32流水灯程序的时候,看到了"GPIO_Init(GPIOB, &GPIO_InitStructure)"这个函数,参数1"GPIOB"很 ...

  3. 【Spark2.0源码学习】-4.Master启动

         Master作为Endpoint的具体实例,下面我们介绍一下Master启动以及OnStart指令后的相关工作   一.脚本概览      下面是一个举例: /opt/jdk1..0_79/ ...

  4. oracle表信息

    获取表: select table_name from user_tables; //当前用户的表 select table_name from all_tables; //所有用户的表 select ...

  5. hdu1054最小顶点覆盖

    最小定点覆盖是指这样一种情况: 图G的顶点覆盖是一个顶点集合V,使得G中的每一条边都接触V中的至少一个顶点.我们称集合V覆盖了G的边.最小顶点覆盖是用最少的顶点来覆盖所有的边.顶点覆盖数是最小顶点覆盖 ...

  6. 从性能角度看react组件拆分的重要性

    React是一个UI层面的库,它采用虚拟DOM技术减少Javascript与真正DOM的交互,提升了前端性能:采用单向数据流机制,父组件通过props将数据传递给子组件,这样让数据流向一目了然.一旦组 ...

  7. laravel5 事务回滚

    方法一 //不需要引入,直接开干 public function Transaction(){ DB::beginTransaction(); //开启事务 $sql1 = DB::table('de ...

  8. ER模型的学习

    (计应154兰家才)在建立表后开始了学习的第一步,了解数据库的基本知识,就以建立bbs论坛为标准学习er模型,首先建立了4个表分别是BBSReply,BBSSection,BBSTopic,BBSUs ...

  9. asp.net Socket的简单Web Server

    1.首先初始化socket,包含对端点以及对连接队列长度的初始化 IPAddress address = IPAddress.Loopback; IPEndPoint endPoint = ); So ...

  10. python通过http请求发送soap报文进行webservice接口调用

    最近学习Python调用webservice 接口,开始的时候主要采用suds 的方式生产client调用,后来发现公司的短信接口采用的是soap报文来调用的,然后开始了谷歌,最后采用httplib ...