Node.js 适配器模式

栏目: Node.js · 发布时间: 5年前

内容简介:适配器模式可以让我们使用一个不同的接口来访问一个对象的功能。它用来适配一个对象,来让期望一个不同接口的组件可以使用它。如下图所示:Adapter 实际就是 Adaptee 的封装,导出一个不同的接口。如图所示,Adapter 的接口也可以是 Adaptee 中一个或多个方法的组合。 这个模式非常直观,我们直接来看一个例子。我们围绕 LevelUP API 来构建一个适配器,把它变成一个兼容核心 fs 模块的接口。 尤其是,我们将确保每次调用 readFile() 和 writeFile() 都将转成到 db

适配器模式

Node.js 适配器模式

适配器模式可以让我们使用一个不同的接口来访问一个对象的功能。它用来适配一个对象,来让期望一个不同接口的组件可以使用它。如下图所示:

Adapter 实际就是 Adaptee 的封装,导出一个不同的接口。如图所示,Adapter 的接口也可以是 Adaptee 中一个或多个方法的组合。 这个模式非常直观,我们直接来看一个例子。

从文件系统API使用 LevelUP

我们围绕 LevelUP API 来构建一个适配器,把它变成一个兼容核心 fs 模块的接口。 尤其是,我们将确保每次调用 readFile() 和 writeFile() 都将转成到 db.get() 和 db.put() 的调用;这样我们就可以把 LevelUP 数据库当做简单文件系统操作的一个存储后台。

我们从创建一个名为 fsAdapter.js 的模块开始。我们将从加载依赖开始,然后导出我们将用来构建适配器的 createFsAdapter() 工厂:

var path = require('path');

module.exports = function createFsAdapter(db) {
	var fs = {};
		//... 继续
}

下面,我们来实现工厂内部的 readFile() 函数,并确保它的接口跟 fs 模块的原生接口之一是兼容的:

fs.readFile = function(filename, options, callback) {
	if (typeof options === 'function') {
		callback = option;
		options = {};
	} else if (typeof options === 'string') {
		options = {encoding: options};
	}

	db.get(path.resolve(filename), {	//[1]
		valueEncoding: options.encoding
		},
		function(err, value) {
			if (err) {
				if (err.type === 'NotFoundError') {	//[2]
					err = new Error('ENOENT, open \'' + filename + '\'');
					err.code = 'ENOENT';
					err.errno = 34;
					err.path = filename;
				}
				return callback && callback(err);
			}
			callback && callback(null, value);	//[3]
		}
	);
};

在上述代码中,我们必须做一些额外工作确保我们新函数的行为跟原始的 fs.readFile() 函数要尽可能接近。各步骤描述如下:

  1. 要从 db 类获取一个文件,我们使用 filename 作为索引来调用 db.get(),并确保总是使用它的全路径(通过使用 path.resolve())。我们把数据库使用的 valueEncoding 设置成跟从输入拿到的 encoding 选项相同。
  2. 如果key在数据库中没找到,我们就使用 ENOENT 作为错误代码来生成一个错误,这个是 fs 模块用来通知一个缺失文件的。其他任何类型的错误都被前转给 callback(我们在这个例子中,只处理了最常见的错误情况)
  3. 如果 key-value 对被成功从数据库获取,我们将使用 callback 把这些值返回给调用者。

实现粗燥,大致可用。

我们再来实现 writeFile() 函数:

fs.writeFile = function(filename, contents, options, callback) {
	if (typeof options === 'function') {
		callback = options;
		options = {};
	} else if (typeof options === 'string') {
		options = {encoding: options};
	}

	db.put(path.resolve(filename), contents, {
		valueEncoding: options.encoding
	}, callback);
}

最后,返回 fs 对象就好:

return fs;

我们可以写一个小的测试模块来试一下:

var fs = require('fs');

fs.writeFile('file.txt', 'Hello', function() {
	fs.readFile('file.txt', {encoding: 'utf8'}, function(err, res) {
		console.log(res);
	});
});

// try to read a missing file
fs.readFile('missing.txt', {encoding: 'utf8'}, function(err, res) {
	console.log(err);
});

我是不是可以搞一章 fs module 和 Adapter 模式

现在我们可以把 fs 模块换成我们的适配器了,如下:

var levelup = require('level');
var fsAdapter = require('./fsAdapter');
var db = levelup('./fsDB', {valueEncoding: 'binary'});
var fs = fsAdapter(db);

Adapter 模式在跟浏览器共享代码中扮演非常重要的角色。

实践中

现实世界中使用适配器的例子数不胜数,可以去探索和分析下列值得关注的示例:

跟不同的翻译引擎进行适配,跟不同的短信网关进行适配

* 示例的完整实现是 level-filesystem( https://www.npmjs.org/package/level-filesystem)。

从核心 API 里面分组,并和模式结合进行讲解,术道并重。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Single Page Web Applications

Single Page Web Applications

Michael Mikowski、Josh Powell / Manning Publications / 2013-9-30 / USD 44.99

Code for most web sites mostly runs on the server. When a user clicks on a link, the site reacts slowly because the browser sends information to the server and the server sends it back again before di......一起来看看 《Single Page Web Applications》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

html转js在线工具
html转js在线工具

html转js在线工具