Iterator 设计模式是行为模式中的一个。 Iterator 模式用于提供通过对象组的标准方式。 Iterator 模式在 [Java Collection Framework](/community/tutorials/collections-in-java-tutorial Java Collections Framework Tutorial
)中被广泛使用。
Iterator 设计模式
According to GoF, iterator design pattern intent is:
提供一种方法来访问聚合对象的元素,而不暴露其潜在的代表性。
Iterator 模式不仅仅是通过集合,我们可以根据我们的要求提供不同类型的迭代器。Iterator 设计模式隐藏了通过集合的实际实现,客户端程序只使用迭代器方法。
Iterator 模式示例
让我们用一个简单的例子来理解迭代器模式。假设我们有无线电频道的列表,客户端程序想要通过它们一个接一个或基于频道的类型。例如,一些客户端程序只对英语频道感兴趣,只想处理它们,他们不想处理其他类型的频道。所以我们可以向客户端提供频道的集合,并让他们写出通过频道的逻辑,并决定是否处理它们。但是这个解决方案有很多问题,比如客户端必须提出通道的逻辑。我们不能确保客户端逻辑是正确的。此外,如果客户端的数量增加,那么它将变得非常难维护。在这里,我们可以使用Iter模式,并根据频道类型提供迭代。我们应该确保客户端程序只能通过Iterator访问频道列表。实施的第一部分是为我们的收集器和
1package com.journaldev.design.iterator;
2
3public enum ChannelTypeEnum {
4
5 ENGLISH, HINDI, FRENCH, ALL;
6}
ChannelTypeEnum是 [java enum](/community/tutorials/java-enum Java Enum
),它定义了所有不同类型的频道。
1package com.journaldev.design.iterator;
2
3public class Channel {
4
5 private double frequency;
6 private ChannelTypeEnum TYPE;
7
8 public Channel(double freq, ChannelTypeEnum type){
9 this.frequency=freq;
10 this.TYPE=type;
11 }
12
13 public double getFrequency() {
14 return frequency;
15 }
16
17 public ChannelTypeEnum getTYPE() {
18 return TYPE;
19 }
20
21 @Override
22 public String toString(){
23 return "Frequency="+this.frequency+", Type="+this.TYPE;
24 }
25
26}
Channel 是一个简单的 POJO 类,具有属性频率和频道类型。
1package com.journaldev.design.iterator;
2
3public interface ChannelCollection {
4
5 public void addChannel(Channel c);
6
7 public void removeChannel(Channel c);
8
9 public ChannelIterator iterator(ChannelTypeEnum type);
10
11}
ChannelCollection 界面定义了我们收藏类实现的合同。请注意,有方法可以添加和删除频道,但没有方法可以返回频道列表。
1package com.journaldev.design.iterator;
2
3public interface ChannelIterator {
4
5 public boolean hasNext();
6
7 public Channel next();
8}
现在我们的基本界面和核心类已经准备好了,让我们继续实施收藏类和迭代器。
1package com.journaldev.design.iterator;
2
3import java.util.ArrayList;
4import java.util.List;
5
6public class ChannelCollectionImpl implements ChannelCollection {
7
8 private List<Channel> channelsList;
9
10 public ChannelCollectionImpl() {
11 channelsList = new ArrayList<>();
12 }
13
14 public void addChannel(Channel c) {
15 this.channelsList.add(c);
16 }
17
18 public void removeChannel(Channel c) {
19 this.channelsList.remove(c);
20 }
21
22 @Override
23 public ChannelIterator iterator(ChannelTypeEnum type) {
24 return new ChannelIteratorImpl(type, this.channelsList);
25 }
26
27 private class ChannelIteratorImpl implements ChannelIterator {
28
29 private ChannelTypeEnum type;
30 private List<Channel> channels;
31 private int position;
32
33 public ChannelIteratorImpl(ChannelTypeEnum ty,
34 List<Channel> channelsList) {
35 this.type = ty;
36 this.channels = channelsList;
37 }
38
39 @Override
40 public boolean hasNext() {
41 while (position < channels.size()) {
42 Channel c = channels.get(position);
43 if (c.getTYPE().equals(type) || type.equals(ChannelTypeEnum.ALL)) {
44 return true;
45 } else
46 position++;
47 }
48 return false;
49 }
50
51 @Override
52 public Channel next() {
53 Channel c = channels.get(position);
54 position++;
55 return c;
56 }
57
58 }
59}
请注意 **内部类**实现迭代器接口,以便实现不能被任何其他集合使用。相同的方法也跟随集合类,它们都有Iterator接口的内部类实现。让我们写一个简单的迭代器模式测试程序来使用我们的集合和迭代器来穿过频道集合。
1package com.journaldev.design.iterator;
2
3public class IteratorPatternTest {
4
5 public static void main(String[] args) {
6 ChannelCollection channels = populateChannels();
7 ChannelIterator baseIterator = channels.iterator(ChannelTypeEnum.ALL);
8 while (baseIterator.hasNext()) {
9 Channel c = baseIterator.next();
10 System.out.println(c.toString());
11 }
12 System.out.println("******");
13 // Channel Type Iterator
14 ChannelIterator englishIterator = channels.iterator(ChannelTypeEnum.ENGLISH);
15 while (englishIterator.hasNext()) {
16 Channel c = englishIterator.next();
17 System.out.println(c.toString());
18 }
19 }
20
21 private static ChannelCollection populateChannels() {
22 ChannelCollection channels = new ChannelCollectionImpl();
23 channels.addChannel(new Channel(98.5, ChannelTypeEnum.ENGLISH));
24 channels.addChannel(new Channel(99.5, ChannelTypeEnum.HINDI));
25 channels.addChannel(new Channel(100.5, ChannelTypeEnum.FRENCH));
26 channels.addChannel(new Channel(101.5, ChannelTypeEnum.ENGLISH));
27 channels.addChannel(new Channel(102.5, ChannelTypeEnum.HINDI));
28 channels.addChannel(new Channel(103.5, ChannelTypeEnum.FRENCH));
29 channels.addChannel(new Channel(104.5, ChannelTypeEnum.ENGLISH));
30 channels.addChannel(new Channel(105.5, ChannelTypeEnum.HINDI));
31 channels.addChannel(new Channel(106.5, ChannelTypeEnum.FRENCH));
32 return channels;
33 }
34
35}
当我运行程序以上时,它会产生以下输出;
1Frequency=98.5, Type=ENGLISH
2Frequency=99.5, Type=HINDI
3Frequency=100.5, Type=FRENCH
4Frequency=101.5, Type=ENGLISH
5Frequency=102.5, Type=HINDI
6Frequency=103.5, Type=FRENCH
7Frequency=104.5, Type=ENGLISH
8Frequency=105.5, Type=HINDI
9Frequency=106.5, Type=FRENCH
10******
11Frequency=98.5, Type=ENGLISH
12Frequency=101.5, Type=ENGLISH
13Frequency=104.5, Type=ENGLISH
Iterator 设计模式 重要点
- Iterator 模式是有用的,当你想提供一个标准的方式来迭代集合,并隐藏实现逻辑从客户端程序. *迭代的逻辑嵌入到集合本身,它有助于客户端程序轻松迭代它们。
JDK 中的 Iterator 设计模式
我们都知道集合框架Iterator是迭代器模式实现的最佳例子,但你知道‘java.util.Scanner’类也实现了Iterator界面。阅读本文以了解关于Java Scanner Class(/community/tutorials/scanner-class-in-java)。