迭代模式是行为模式之一,它把对容器中包含的内部对象的访问委让给外部类,使用Iterator(遍历)按顺序进行遍历访问的设计模式。
在应用Iterator模式之前,首先应该明白Iterator模式用来解决什么问题。或者说,如果不使用Iterator模式,会存在什么问题。
1.由容器自己实现顺序遍历。直接在容器类里直接添加顺序遍历方法
2.让调用者自己实现遍历。直接暴露数据细节给外部。
以上方法1与方法2都可以实现对遍历,这样就会出现一些问题如:
1,容器类承担了太多功能:一方面需要提供添加删除等本身应有的功能;一方面还需要提供遍历访问功能。
2,往往容器在实现遍历的过程中,需要保存遍历状态,当跟元素的添加删除等功能夹杂在一起,很容易引起混乱和程序运行错误等。
让我们通过一个简单的例子来理解迭代器模式。假设我们有一个无线电信道列表,并且客户端程序希望逐个或基于信道类型遍历它们。例如,一些客户端程序仅对英语频道感兴趣并且想要仅处理它们,他们不想处理其他类型的频道。
因此,我们可以向客户端提供一组通道,让他们编写逻辑来遍历通道并决定是否处理它们。但是这个解决方案有很多问题,比如客户端必须提出遍历的逻辑。我们无法确保客户端逻辑是正确的。此外,如果客户端数量增加,那么维护将变得非常困难。
在这里,我们可以使用Iterator模式并根据通道类型提供迭代。我们应该确保客户端程序只能通过迭代器访问通道列表。
实现的第一部分是为我们的集合和迭代器接口定义合同。
package com.journaldev.design.iterator;
public enum ChannelTypeEnum {
ENGLISH, HINDI, FRENCH, ALL;
}
Channel是一个简单的POJO类,具有属性频率和通道类型。
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;
}
}
ChannelCollection接口定义了我们的集合类实现的契约:
package com.journaldev.design.iterator;
public interface ChannelCollection {
public void addChannel(Channel c);
public void removeChannel(Channel c);
public ChannelIterator iterator(ChannelTypeEnum type);
}
package com.journaldev.design.iterator;
public interface ChannelIterator {
public boolean hasNext();
public Channel next();
}
现在我们的基本接口和核心类已准备就绪,让我们继续执行集合类和迭代器。
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接口的内部类实现。
让我们编写一个简单的迭代器模式测试程序,使用我们的集合和迭代器来遍历通道集合。
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;
}
}
运行程序:
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
原文:https://www.cnblogs.com/swpudengyuheng/p/12832940.html