java设计模式迭代器模式
迭代器模式是一种行为模式,它用于提供遍历一组对象的标准方式。 Iterator模式在Java Collection Framework中得到了广泛使用,其中Iterator接口提供了遍历集合的方法。 根据GoF,迭代器设计模式的意图是:
提供一种在不暴露其基础表示的情况下访问聚合对象的元素的方法。
迭代器模式不仅涉及遍历集合,我们还可以根据需求提供不同种类的迭代器。 迭代器模式通过集合隐藏了遍历的实际实现,而客户端程序仅使用迭代器方法。
让我们通过一个简单的例子来了解这种模式。 假设我们有一个广播频道列表,并且客户端程序要逐个或根据频道类型遍历它们,例如,某些客户端程序只对英语频道感兴趣,并且只想处理它们,而没有想要处理其他类型的渠道。
因此,我们可以向客户提供渠道的集合,让他们编写逻辑来遍历渠道并决定是否进行处理。 但是此解决方案存在很多问题,例如客户端必须提出遍历的逻辑。 我们无法确保客户端逻辑正确,并且如果客户端数量增加,则将很难维护。
在这里,我们可以使用Iterator模式,并根据通道类型提供迭代。 我们应该确保客户端程序只能通过迭代器访问频道列表。
实现的第一部分是为我们的collection和iterator接口定义协定。
ChannelTypeEnum.java
package com.journaldev.design.iterator;
public enum ChannelTypeEnum {
ENGLISH, HINDI, FRENCH, ALL;
}
ChannelTypeEnum是Java枚举 ,它定义所有不同类型的通道。
Channel.java
package com.journaldev.design.iterator;
public class Channel {
private double frequency;
private ChannelTypeEnum TYPE;
public Channel(double freq, ChannelTypeEnum type){
this.frequency=freq;
this.TYPE=type;
}
public double getFrequency() {
return frequency;
}
public ChannelTypeEnum getTYPE() {
return TYPE;
}
@Override
public String toString(){
return "Frequency="+this.frequency+", Type="+this.TYPE;
}
}
通道是一个简单的POJO类,具有频率和通道类型属性。
ChannelCollection.java
package com.journaldev.design.iterator;
public interface ChannelCollection {
public void addChannel(Channel c);
public void removeChannel(Channel c);
public ChannelIterator iterator(ChannelTypeEnum type);
}
ChannelCollection接口为我们的集合类实现定义合同。 请注意,有一些方法可以添加和删除通道,但是没有方法可以返回通道列表,而有一个方法可以返回遍历的迭代器。 ChannelIterator接口定义以下方法;
ChannelIterator.java
package com.journaldev.design.iterator;
public interface ChannelIterator {
public boolean hasNext();
public Channel next();
}
现在我们的基本接口和核心类已经准备好,让我们继续实现collection类和迭代器。
ChannelCollectionImpl.java
package com.journaldev.design.iterator;
import java.util.ArrayList;
import java.util.List;
public class ChannelCollectionImpl implements ChannelCollection {
private List<Channel> channelsList;
public ChannelCollectionImpl() {
channelsList = new ArrayList<>();
}
public void addChannel(Channel c) {
this.channelsList.add(c);
}
public void removeChannel(Channel c) {
this.channelsList.remove(c);
}
@Override
public ChannelIterator iterator(ChannelTypeEnum type) {
return new ChannelIteratorImpl(type, this.channelsList);
}
private class ChannelIteratorImpl implements ChannelIterator {
private ChannelTypeEnum type;
private List<Channel> channels;
private int position;
public ChannelIteratorImpl(ChannelTypeEnum ty,
List<Channel> channelsList) {
this.type = ty;
this.channels = channelsList;
}
@Override
public boolean hasNext() {
while (position < channels.size()) {
Channel c = channels.get(position);
if (c.getTYPE().equals(type) || type.equals(ChannelTypeEnum.ALL)) {
return true;
} else
position++;
}
return false;
}
@Override
public Channel next() {
Channel c = channels.get(position);
position++;
return c;
}
}
}
注意迭代器接口的内部类实现,以便任何其他集合都不能使用该实现。 集合类也遵循相同的方法,并且它们都具有Iterator接口的内部类实现。
让我们编写一个简单的测试类,以使用我们的集合和迭代器根据类型遍历通道的集合。
IteratorPatternTest.java
package com.journaldev.design.iterator;
public class IteratorPatternTest {
public static void main(String[] args) {
ChannelCollection channels = populateChannels();
ChannelIterator baseIterator = channels.iterator(ChannelTypeEnum.ALL);
while (baseIterator.hasNext()) {
Channel c = baseIterator.next();
System.out.println(c.toString());
}
System.out.println("******");
// Channel Type Iterator
ChannelIterator englishIterator = channels.iterator(ChannelTypeEnum.ENGLISH);
while (englishIterator.hasNext()) {
Channel c = englishIterator.next();
System.out.println(c.toString());
}
}
private static ChannelCollection populateChannels() {
ChannelCollection channels = new ChannelCollectionImpl();
channels.addChannel(new Channel(98.5, ChannelTypeEnum.ENGLISH));
channels.addChannel(new Channel(99.5, ChannelTypeEnum.HINDI));
channels.addChannel(new Channel(100.5, ChannelTypeEnum.FRENCH));
channels.addChannel(new Channel(101.5, ChannelTypeEnum.ENGLISH));
channels.addChannel(new Channel(102.5, ChannelTypeEnum.HINDI));
channels.addChannel(new Channel(103.5, ChannelTypeEnum.FRENCH));
channels.addChannel(new Channel(104.5, ChannelTypeEnum.ENGLISH));
channels.addChannel(new Channel(105.5, ChannelTypeEnum.HINDI));
channels.addChannel(new Channel(106.5, ChannelTypeEnum.FRENCH));
return channels;
}
}
当我运行上面的程序时,它会产生以下输出;
IteratorPatternTest.java
Frequency=98.5, Type=ENGLISH
Frequency=99.5, Type=HINDI
Frequency=100.5, Type=FRENCH
Frequency=101.5, Type=ENGLISH
Frequency=102.5, Type=HINDI
Frequency=103.5, Type=FRENCH
Frequency=104.5, Type=ENGLISH
Frequency=105.5, Type=HINDI
Frequency=106.5, Type=FRENCH
******
Frequency=98.5, Type=ENGLISH
Frequency=101.5, Type=ENGLISH
Frequency=104.5, Type=ENGLISH
重要事项
- 当您想提供一种标准方法来迭代集合并从客户端程序中隐藏实现逻辑时,迭代器模式非常有用。
- 迭代逻辑嵌入在集合本身中,它可以帮助客户端程序轻松地对其进行迭代。
JDK中的迭代器模式
我们都知道Collection框架Iterator是迭代器模式实现的最佳示例,但是您知道java.util.Scanner
类也实现Iterator接口。 阅读这篇文章以了解Java扫描程序类。
这就是迭代器模式的全部内容,我希望它会有所帮助并且易于理解。
翻译自: https://www.javacodegeeks.com/2013/08/iterator-design-pattern-in-java-example-tutorial.html
java设计模式迭代器模式