【设计模式系列】之【迭代器模式】

前言:要提升代码水平,就绕不开设计模式。之前也有过一些了解,但并没有深入学习。最近准备系统的学习一下设计模式,提高设计,解耦的能力,发现了一本好书《JavaScript设计模式与开发实践》,所以边读边写,把常用的设计模式学习并记录在这里。

迭代器模式

    • 定义与介绍
      • 内部迭代器 和 外部迭代器
    • JavaScript中的迭代器模式
    • 迭代器模式的例子

定义与介绍

迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。

迭代器模式是一种相对简单的设计模式,简单到很多时候我们都不认为它是一种设计模式,目前绝大部分语言都内置了迭代器。

现代语言中都内置了迭代器,比如js中的Array.prototype.forEach。我们也可以自己实现一个迭代器:

const each = (arr, cb) {
	for(let i=0; i<arr.length; i++){
		cb.call(arr[i], i, arr[i]);
	}
}

内部迭代器 和 外部迭代器

我们在js中常用的forEach就是内部迭代器,在其内部已经定义好了迭代规则,他完全接手整个迭代过程,外部只需要初始调用一次即可。

外部迭代器必须显式的请求迭代下一个元素。比如:

const Iterator = function(arr) {
	const current = 0;
	const next = function(){
		current += 1;
	}
	const isDone = function(){
		return current >= arr.length;
	}
	const getCurrentItem = function(){
		return arr[current];
	}
	return {
		next,
		isDone,
		getCurrentItem,
	}
}

// 使用时,通过
Iterator.isDone() //判断是否迭代完成
Iterator.next() //显式调用进行一次迭代
Iterator.getCurrentItem() //获取当前项

JavaScript中的迭代器模式

Array.prototype.forEach

迭代器模式的例子

假设之前的代码中,有这样一个需求:上传文件时根据不同的浏览器来获取相应的上传组件对象。


// 原来的代码
const getUploadObj = function() {
	try{
		return new ActiveXObject('TXFTNActive.FTNUpload'); // IE上传控件
	} cache(e) {
		if(supportFlash()){ // 是否支持flash
			const str = '';
			return $(str).appendTo($('body'));
		} else {
			const str = ''; // 表单上传
			return $(str).appendTo($('body'));
		}
	}
}

这样的代码明显很乱,而且各种上传方法之间没有解耦,如果要新增其他的,还要增加if else分支,违反开放封闭原则。

下面我们换个思路,我们有多种上传方式,只需要按优先级迭代每一种方式,如果适用则返回对象,否则返回false,直到获取一个可用的为止。当然,这要求我们对于每一种方式,都要在可用时返回对象,不可用时返回false。保证函数的输入输出一致。

代码:

// IE上传控件
const getActiveUpoladObj = function() {
	try{
		return new ActiveXObject('TXFTNActive.FTNUpload');
	} cache(e) {
		return false;
	}
}
// flash上传
const getFlashUpoladObj = function() {
	const str = '';
	return $(str).appendTo($('body'));
}
// 表单上传
const getFormUpoladObj = function() {
	const str = '';
			return $(str).appendTo($('body'));
}

// 迭代器
const iteratorUploadObj = function() {
	for(let i=0; i<arguments.length; i++) {
		let uploadObj = fn();
		if(uploadObj !== false) {
			return uploadObj;
		}
	}
}

// 使用
const uploadObj = iteratorUploadObj(getActiveUpoladObj, getFlashUpoladObj, getFormUpoladObj);

你可能感兴趣的:(设计模式)