将 类的接口 转换成用户可以调用的 另外一个接口,使接口不兼容的两个类可以一起工作;
适用场景:
- 功能正确但接口不匹配:对于之前开发好的类,该类的操作和返回值都是正确的,但是其定义的方法接口无法调用,此时使用适配器模式,使该类与用户的接口匹配,让用户使用适配器的接口 ,间接调用该类;
- 适配器模式使用阶段:软件设计开发阶段一般不使用适配器模式,在软件维护时,出现操作和返回值类似,但是函数接口不同,为了适配第三方系统的接口,使用适配器模式;
适配器模式 优点:
- 复用且不修改类:不改变现有类的基础上, 提高类的复用性, 透明性 ; 让现有类与目标类接口匹配;
- 降低耦合:目标类 ( 用户调用的接口所在类 ) 和 现有类 ( 被适配者 ) 解除耦合, 降低了系统的耦合性, 易于扩展维护;
- 符合开闭原则: 用户调用适配器接口, 只与适配器类进行交互, 如果需要修改扩展, 只需要修改适配器类即可, 目标类 和 现有类 各自都是相互独立的, 互不影响;
适配器模式 优点:
- 增加复杂性:编写适配器类时, 需要考虑全面, 包括被适配者 和 目标类, 系统复杂性会增加;
- 降低可读性:系统代码可读性降低, 可维护性降低;
类图
代码
class Power {
charge() {
return '220V';
}
}
class Adapter {
constructor() {
this.power = new Power();
}
charge() {
let power = this.power.charge();
return `${power} => 12V`;
}
}
class Client {
constructor() {
this.adapter = new Adapter();
}
use() {
console.log(this.adapter.charge());
}
}
new Client().use();
// 220V => 12V
经典场景
插件适配
function ajax(options) {
let _default = {
method: 'GET',
dataType: 'json'
}
// 适配参数
for (let attr in options) {
_default[attr] = options[attr] || _default[attr];
}
}
function get(url) {
let options = { method: 'GET', url };
ajax(options);
}
promisify
let fs = require('fs');
function promisify(readFile) {
return function (filename, encoding) {
return new Promise(function (resolve, reject) {
readFile(filename, encoding, function (err, data) {
if (err)
reject(err);
else
resolve(data);
})
});
}
}
// 让 readFile 适配 promise 写法
let readFile = promisify(fs.readFile);
let one = await readFile('./1.txt', 'utf8');
let two = await readFile('./2.txt', 'utf8');
let three = await readFile('./3.txt', 'utf8');
jquery
let $ = require('jquery');
// 以前用 ajax 请求接口
$.ajax({
url,
type: 'POST',
dataType: 'json',
data: { id: 1 }
});
// 现在某些环境需要用 fetch,为了兼容需要做适配
let $ = {
ajax(options) {
fetch(options.url, {
method: options.type,
body: JSON.stringify(options.data)
})
}
}
打赏作者
您的打赏是我前进的动力
微信
支付宝
单例模式
上一篇
评论