设计模式10-Iterator

本文最后更新于:3 years ago

迭代器模式

  迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。

迭代器模式属于 行为型模式

如果想了解迭代器模式的具体的介绍,菜鸟教程介绍得比较详细↓
菜鸟教程-迭代器模式

结构图


优缺点

优点:

1、它支持以不同的方式遍历一个聚合对象。
2、迭代器简化了聚合类。
3、在同一个聚合上可以有多个遍历。
4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

缺点: 由于在客户端和真实主题之间增加了代理对象,因此有些类型的迭代器模式可能会造成请求的处理速度变慢。
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

使用场景

1、访问一个聚合对象的内容而无须暴露它的内部表示。
2、需要为聚合对象提供多种遍历方式。
3、为遍历不同的聚合结构提供一个统一的接口。

实现代码

迭代器这个模式,其实在学Java的时候,相信大家就已经接触过了,所以这里就简单介绍一下。
这个可以去看看ArrayList、LinkList…这些容器的迭代器部分的源码(看源码真的能够学到很多知识!)

新的一天开始了,甲方爸爸为了使你成长,对你提出需求,构造一个容器,可以动态扩展:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 数组来实现容器
class ArrayList_{
Object[] object = new Object[10];
//Object中下一个空的位置在哪儿,或者说,目前容器中有多少个元素
private int index = 0;
public void add(Object o){
if (index == object.length){
Object[] newObject = new Object[object.length*2];
System.arraycopy(object, 0, newObject, 0, object.length);
object = newObject;
}
object[index++] = o;
}

public int size(){
return index;
}
}

// 链表实现容器
class LinkList_{
Node head = null;
Node tail = null;

private int index = 0;

public void add(Object o){
Node n = new Node(o);
n.next = null;

if (head == null){
head = n;
tail = n;
}

tail.next = n;
tail = n;
index++;
}

private class Node{
private Object object;
Node next;

public Node(Object o){
object = o;
}
}

public int size(){
return index;
}
}

这里实现了两种容器,一种是用数组来实现的,一种是用链表实现的。(任何容器都是由这两种结构来实现的)

接着将两种容器,整合一下,实现容器的替换。这里我们只要将两种容器实现一个接口就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public interface Collection_ {
void add(Object o);
int size();
}

public class ArrayList_ implements Collection_{
Object[] object = new Object[10];
//Object中下一个空的位置在哪儿,或者说,目前容器中有多少个元素
private int index = 0;

@Override
public void add(Object o){
if (index == object.length){
Object[] newObject = new Object[object.length*2];
System.arraycopy(object, 0, newObject, 0, object.length);
object = newObject;
}
object[index++] = o;
}

@Override
public int size(){
return index;
}
}

public class LinkList_ implements Collection_{
Node head = null;
Node tail = null;

private int index = 0;

public void add(Object o){
Node n = new Node(o);
n.next = null;

if (head == null){
head = n;
tail = n;
}

tail.next = n;
tail = n;
index++;
}

private class Node{
private Object object;
Node next;

public Node(Object o){
object = o;
}
}

public int size(){
return index;
}
}

public class Main {
public static void main(String[] args) {
Collection_ list = new ArrayList_();
for (int i = 0; i < 20; i++) {
list.add(new String("s") + i);
}

System.out.println(list.size());
}
}

ArrayList_和LinkList_都实现了Collection_接口,重写了add()和size()方法。

到这里,前期准备工作就完成了。

接着,甲方爸爸又提出新的需求,我要将容器中的所有数据取出来,并且这个遍历是通用的。
也就是我数组容器可以遍历,链表容器也可以遍历,以后的Hash,Queue…都可以用这个遍历。

麻烦了

1
2
3
4
ArrayList_ al = (ArrayList_)list;
for (int i = 0; i < al.size(); i++) {
//如果用这种方式变量,就不能实现互通了
}

你是不是准备这样做,但是甲方爸爸不让你这样做。

于是咋办,你想了想,计从心来:

创建一个Iterator接口,然后让这些容器,自己来实现这些遍历

你很快写下来以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
public interface Iterator_ {
boolean hasNext();

Object next();
}

public interface Collection_ {
void add(Object obj);

int size();

Iterator_ iterator();
}

public class ArrayList_ implements Collection_{
Object[] objects = new Object[10];

private int index = 0;

@Override
public void add(Object obj) {
if (index == objects.length){
Object[] newObject = new Object[objects.length*2];
System.arraycopy(objects, 0, newObject, 0, objects.length);
objects = newObject;
}
objects[index++] = obj;
}

@Override
public int size() {
return index;
}

@Override
public Iterator_ iterator() {
return new ArrayListIterator();
}

private class ArrayListIterator implements Iterator_{

private int currentIndex = 0;

@Override
public boolean hasNext() {
if (index > currentIndex) return true;
else return false;
}

@Override
public Object next() {
Object obj = objects[currentIndex];
currentIndex++;
return obj;
}
}
}

public class LinkList_ implements Collection_ {
Node head = null;
Node tail = null;

private int index = 0;

@Override
public void add(Object obj) {
Node node = new Node(obj);
node.next = null;

if (head == null) {
head = node;
tail = node;
}

tail.next = node;
tail = node;
index++;
}

private class Node {
Object o;
Node next;

public Node(Object o) {
this.o = o;
}
}

@Override
public int size() {
return index;
}

@Override
public Iterator_ iterator() {
return new ArrayListIterator();
}

private class ArrayListIterator implements Iterator_{

private int currentIndex = 0;
private Node tmp = head;
private Node lastReturn;

@Override
public boolean hasNext() {
if (index > currentIndex) return true;
else return false;
}

@Override
public Object next() {
lastReturn = tmp;
tmp = tmp.next;
currentIndex++;
return lastReturn.o;
}
}

}

public class Main {
public static void main(String[] args) {
Collection_ list = new LinkList_();
for (int i = 0; i < 20; i++) {
list.add(new String("s") + i);
}

Iterator_ iterator = list.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
}
}

这里是将,Iterator接口定义在Collection接口中,然后由容器内部将Iterator接口实现(完美)


  就这样,你又一次完成了甲方爸爸的需求,但是你没有上次开心,是啊,摸鱼划水谁不想呢?


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!