迭代器(iterrator)模式是一种行为设计模式,用于提供一种标准的方式来遍历一组对象,它被广泛的用在java Collection架构中提供一种标准接口用来遍历Collection元素。
迭代器模式不仅用于容器(collection)遍历,根据我们需求也可以提供不同类型的迭代器。迭代器模式隐藏了容器具体的实现方式,只给客户端提供遍历方法。
让我们用一种简单的例子来理解这种模式。假设我们有一个广播频道列表,用户想通过频道类型进行遍历,在这个例子中某些用户只对英文频道感兴趣,仅对它们进行处理,
不想对其它类型频道进行处理。
所以我们要提供一个频道容器给客户端,根据写入的逻辑来遍历频道并处理它们,但是客户的逻辑可能会有很多问题,我们不能确定客户端逻辑是否正确,如果客户数量的增长,那么它会变得非常难以维护。
这里我们提供根据频道类型来使用迭代器模式。我们确保客户端只能通过迭代访问频道列表。
第一部分我们制定我们的容器实现规则和iterrator接口:
ChannelTypeEnum.java
package com.journaldev.design.iterator; public enum ChannelTypeEnum { ENGLISH, HINDI, FRENCH, ALL; }
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; } }Channel用频率和频道类型属性
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.java 制订了我们实现类规则,注意那些方法只提供了add,remove一个频道,但是没有提供返回整个频道列表方法,只有一个返回iterater对象用于遍历,
ChannelIterator定义如下方法:
package com.journaldev.design.iterator; public interface ChannelIterator { public boolean hasNext(); public Channel next(); }
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; } } }
我们使用一个简单测试程序使用我们的容器,根据频道类型对容器使用iterater对其进行遍历。
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