JAVA SCRIPT设计模式是本人根据GOF的设计模式写的博客记录。使用JAVA SCRIPT语言来实现主体功能,所以不可能像C++,JAVA等面向对象语言一样严谨,大部分程序都附上了JAVA SCRIPT代码,代码只是实现了设计模式的主体功能,不代表全部的正确,特此声明。若读者需要了解设计模式目录、原则、设计变化方向,环境相关等信息请查看设计模式开篇。
一、UML类图
参与者:
1.1 Iterator(迭代器)
- 迭代器定义访问和遍历元素的接口。
1.2 ConcreteIterator(具体迭代器)
- 具体迭代器实现迭代器接口。
- 对该聚合遍历时跟踪当前位置。
1.3 Aggregate(聚合)
- 聚合定义创建相应迭代器对象的接口。
1.4 ConcreteAggregate(具体聚合)
- 具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例。
二、意图
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。
三、适用性
- 访问一个聚合对象的内容而无需暴露它的内部表示。
- 支持对聚合对象的多种遍历。
- 为遍历不同的聚合结构提供一个统一的接口(即,支持多态迭代)。
四、示例代码
4.1 动机
一个聚合对象,如列表(list),应该提供一种方法来让别人可以访问它的元素,而又不需暴露它的内部结构.此外,针对不同的需要,可能要以不同的方式遍历这个列表。但是即使可以预见到所需的那些遍历操作,你可能也不希望列表的接口中充斥着各种不同遍历的操作。有时还可能需要在同一个表列上同时进行多个遍历。
迭代器模式都可帮你解决所有这些问题。这一模式的关键思想是将对列表的访问和遍历从列表对象中分离出来并放入一个迭代器(iterator)对象中。迭代器类定义了一个访问该列表元素的接口。迭代器对象负责跟踪当前的元素;即,它知道哪些元素已经遍历过了。
例如,一个列表(List)类可能需要一个列表迭代器(ListIterator),它们之间的关系如下图:
在实例化列表迭代器之前,必须提供待遍历的列表。一旦有了该列表迭代器的实例,就可以顺序地访问该列表的各个元素。CurrentItem操作返回表列中的当前元素,First操作初始化迭代器,使当前元素指向列表的第一个元素,Next操作将当前元素指针向前推进一步,指向下一个元素,而IsDone检查是否已越过最后一个元素,也就是完成了这次遍历。
4.2 示例UML
首先,定义一个抽象列表类AbstractList,它提供操作列表的公共接口。类似地,我们也需要一个抽象的迭代器类Iterator,它定义公共的迭代接口。然后我们可以为每个不同的列表实现定义具体的Iterator子类。这样迭代机制就与具体的聚合类无关了。
目录结构:
4.3 Iterator(迭代器)
- 迭代器定义访问和遍历元素的接口。
export default class Iterator {
listItem=[];
constructor(listItem) {
this.listItem=listItem;
}
First() {
}
Next() {
}
IsDone() {
}
CurrentItem() {
}
}
4.4 ConcreteIterator(具体迭代器)
- 具体迭代器实现迭代器接口。
- 对该聚合遍历时跟踪当前位置。
import Iterator from '../Iterator.js';
export default class OrderListIterator extends Iterator {
index=0;
isDone=false;
constructor(listItem) {
super(listItem);
}
First() {
this.index=0;
if(this.index==this.listItem.length)
this.isDone=true;
}
Next() {
this.index++;
if(this.index==this.listItem.length)
this.isDone=true;
}
IsDone() {
return this.isDone;
}
CurrentItem() {
return this.listItem[this.index];
}
}
import Iterator from '../Iterator.js';
export default class InvertedOrderListIterator extends Iterator {
index=0;
isDone=false;
constructor(listItem) {
super(listItem);
}
First() {
this.index=this.listItem.length-1;
if(this.index<0)
this.isDone=true;
}
Next() {
this.index--;
if(this.index<0)
this.isDone=true;
}
IsDone() {
return this.isDone;
}
CurrentItem() {
return this.listItem[this.index];
}
}
4.5 Aggregate(聚合)
- 聚合定义创建相应迭代器对象的接口。
import Iterator from '../Iterator/Iterator.js';
export default class AbstractList {
listItem=[];
iterator;
constructor( ) {
}
CreateIterator() {
}
Count() {
return this.listItem.size();
}
Append(item) {
this.listItem.push(item);
}
Remove(item) {
}
}
4.6 ConcreteAggregate(具体聚合)
- 具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例。
import AbstractList from '../AbstractList.js';
import OrderListIterator from '../../Iterator/impl/OrderListIterator.js';
export default class OrderList extends AbstractList {
constructor( ) {
super();
}
CreateIterator() {
this.iterator=new OrderListIterator(this.listItem);
return this.iterator;
}
}
import AbstractList from '../AbstractList.js';
import InvertedOrderListIterator from '../../Iterator/impl/InvertedOrderListIterator.js';
export default class InvertedOrderList extends AbstractList {
constructor( ) {
super();
}
CreateIterator() {
this.iterator=new InvertedOrderListIterator(this.listItem);
return this.iterator;
}
}
4.7 Client
import OrderList from './AbstractList/impl/OrderList.js';
import InvertedOrderList from './AbstractList/impl/InvertedOrderList.js';
export default class Client{
constructor(ctx,zooRect) {
let orderList=new OrderList();
orderList.Append('1');
orderList.Append('2');
orderList.Append('3');
orderList.Append('4');
orderList.Append('5');
let iterator=orderList.CreateIterator();
for(iterator.First();!iterator.IsDone();iterator.Next())
{
console.log('顺序输出:'+iterator.CurrentItem());
}
let inverorderList=new InvertedOrderList();
inverorderList.Append('1');
inverorderList.Append('2');
inverorderList.Append('3');
inverorderList.Append('4');
inverorderList.Append('5');
let inveriterator=inverorderList.CreateIterator();
for(inveriterator.First();!inveriterator.IsDone();inveriterator.Next())
{
console.log('倒序输出:'+inveriterator.CurrentItem());
}
}
}
4.8 测试HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="module">
import Client from './Client.js';
var canvas = document.getElementById("mycanvas")
var ctx = canvas.getContext("2d") //create 2d object
let cl = new Client(ctx,{startx:0,starty:0,width:900,height:900});
</script>
</head>
<body>
<canvas id="mycanvas" width=900px height=900px></canvas>
</body>
</html>
测试结果:
Client.js:20 顺序输出:1
Client.js:20 顺序输出:2
Client.js:20 顺序输出:3
Client.js:20 顺序输出:4
Client.js:20 顺序输出:5
Client.js:33 倒序输出:5
Client.js:33 倒序输出:4
Client.js:33 倒序输出:3
Client.js:33 倒序输出:2
Client.js:33 倒序输出:1
五、源代码下载
下载链接:https://pan.baidu.com/s/1XuPqp84cccBNVkbnMY3sKw
提取码:q2ut