定义
迭代器模式,是一种行为设计模式,它提供了一种方法顺序访问一个聚合对象中的各个元素,而又无需暴露该对象的内部表示。
迭代器模式将迭代器逻辑封装到独立的对象中,从而解耦了集合对象的遍历和业务逻辑。
UML 类图
typescript 实现
1. 迭代器接口
interface Iterator<T> {
next(): T;
hasNext(): boolean
}
2. 创建具体迭代器
class ConcreteIterator<T> implements Iterator<T> {
private collection: ConcreteAggregate<T>;
private position: number = 0;
constructor(collection: ConcreteAggregate<T>) {
this.collection = collection;
}
public next(): T {
const result = this.collection.getItems()[this.position];
this.position += 1;
return result;
}
public hasNext(): boolean {
return this.position < this.collection.getSize();
}
}
3. 定义集合接口
interface Aggregate<T> {
createIterator(): Iterator<T>;
}
4. 创建具体集合
class ConcreteAggregate<T> implements Aggregate<T> {
private items: T[] = [];
public getItems(): T[] {
return this.items;
}
public getSize(): number {
return this.items.length;
}
public addItem(item: T): void {
this.items.push(item);
}
public createIterator(): Iterator<T> {
return new ConcreteIterator<T>(this);
}
}
5. 使用示例
const collection = new ConcreteAggregate<string>();
collection.addItem("Item 1");
collection.addItem("Item 2");
collection.addItem("Item 3");
const iterator = collection.createIterator();
while(iterator.hasNext()) {
console.log(iterator.next());
}
通用实现
javascript 语言层面已经有 Iterator 接口,因此无需再定义
[Symbol.iterator],这个属性会返回一个 Iterator 对象。如果实现,那么可以调用 for...of 语法
1. 类实现方式
// 公共代码
export abstract class Aggregate<T> {
private items: T[] = [];
protected constructor(itemOrItems?: T[] | T) {
if(itemOritems !== undefined) {
if(Array.isArray(itemOrItems)) {
this.items.push(...itemOrItems);
} else {
this.items.push(itemOrItems);
}
}
}
public addItem(item: T): void {
this.items.push(item);
}
public createIterator() {
return new ConcreteIterator<T>(this.items);
}
[Symbol.iterator]() {
return new ConcreteIterator<T>(this.items);
}
}
export class ConcreteIterator<T> implements Iterator<T> {
private readonly collection: T[];
private index: number = 0;
constructor(collection: T[]) {
this.collection = collection;
}
public next(): IteratorResult<T> {
if(this.hasNext()) {
return { value: this.collection[this.index++], done: false };
}
return { value: undefined, done: true };
}
public hasNext(): boolean {
return this.index < this.collection.length;
}
}
// 私有代码,使用示例
class RangeAggregate extends Aggregate<number> {
constructor(start: number, end: number) {
super(Array.from( { length: end - stop }, (_, i) => i + start ));
}
}
const range = new RangeAggregate(4, 10);
for(const num of range) {
console.log(num); // 4,5,6,7,8,9
}
2. 函数方式
// 公共代码
export function AggregateFactory<T>(aggregate: {
length: number,
[key: number]: T
}, getter?: (index: number) => T) {
return {
index: 0,
hasNext: function() {
return this.index < aggregate.length;
},
next: function() {
if(this.index < aggregate.length) {
const value = getter ? getter(this.index++) : aggregate[this.index++];
return { value, done: false };
} else {
return { value: undefined, done: true };
}
},
[Symbol.iterator]: function() {
this.index = 0;
return this;
}
}
}
// 私有代码,使用示例
const stepRange = (start: number, stop: number, step: number = 1) => {
const length = Math.ceil((stop - start) / step);
return AggregateFactory(
{
length: length
},
(index) => start + index * step
)
};
for(const num of stepRange(1, 20, 3)) {
console.log(num); // 1, 4, 7, 10, 13, 16, 19
}