Re-learning design patterns (3. Design patterns-iterator patterns)

1. Iterator mode

    Starting from JDK1.2, an Iterator interface is introduced:

public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove();
}

    All those that implement the Iterator interface contain a Iterator<E> iterator()method that makes the caller unaware of which class the iterated object is instantiated by.

    Iterator (Iterator) is widely used in Java collections, which we should be more familiar with, it provides a method for sequential access to each element in the container. This is the iterator pattern we are going to learn today.

1.1, what is the iterator mode

  • definition

    The Iterator pattern is a behavioral design pattern that provides an object to sequentially access a series of data in an aggregate object, while traversing the elements of the collection without exposing the internal representation of the aggregate object (list, stack, tree...).

    The iterator pattern is not just traversing a collection, we can provide different types of iterators according to our needs. However, we rarely implement an iterator by ourselves, and the iterator provided in the java API is completely sufficient.

The structure of the iterator:

    1) Abstract aggregation (Aggregate) role: define the interface for storing, adding, deleting aggregate objects and creating iterator objects;

    2) ConcreteAggregate role: implement an abstract aggregate class and return an instance of a concrete iterator;

    3) Abstract iterator (Iterator) role: define the interface for accessing and traversing aggregate elements, usually including hasNext(), first(), next() and other methods;

    4) Implement the method defined in the abstract iterator interface, complete the traversal of the aggregated object, and record the current position of the traversal.

    The intent of the Iterator pattern is to provide a way to access the elements of an aggregate object without exposing its underlying representation.

1.2. Advantages and disadvantages of iterator mode

  • advantage

    1) In line with the principle of single responsibility, the huge traversal algorithm can be extracted into a separate class to clean up the client code and collection.

    2) In line with the principle of opening and closing, we can implement new types of collections and iterators according to our own needs without modifying the original code.

    3) It has good encapsulation and provides a unified interface for traversing different aggregation structures.

  • shortcoming

    1) If it is a relatively simple collection, using the iterator mode may be an overkill;

    2) Using an iterator may be less efficient than directly traversing the elements of some specialized collection.

1.3. Creation method

    Let's take TV channels as an example and write a custom iterator.

1) Create a new Channel POJO class (Plain Ordinary Java Object-simple java object)

//先声明我们的频道枚举
public enum ChannelTypeEnum {

	CCTV1, CCTV2, CCTV3, JXTV1, JXTV2 ,ALL;
}

//Channel是一个简单的 POJO 类,包含频道号码和频道
public class Channel {

	private Integer number;
	
	private ChannelTypeEnum TYPE;
	
	public Channel(Integer number,ChannelTypeEnum TYPE){
		this.number = number;
		this.TYPE = TYPE;
	}

	public Integer getNumber() {
		return number;
	}

	public void setNumber(Integer number) {
		this.number = number;
	}

	public ChannelTypeEnum getTYPE() {
		return TYPE;
	}

	public void setTYPE(ChannelTypeEnum tYPE) {
		TYPE = tYPE;
	}

	@Override
	public String toString() {
		return this.number+"频道是"+this.TYPE;
	}
	
}

2) Abstract iterator (Iterator) role

public interface ChannelIterator {

	//判断是否还有元素
	public boolean hasNext();
	
	//下个元素
	public Channel next();
	
	//是否是最后一个
	public boolean isLast();
}

3) Abstract aggregation (Aggregate) role

public interface ChannelCollection {

	public void addChannel(Channel c);
	
	public void removeChannel(Channel c);
	
	public ChannelIterator iterator(ChannelTypeEnum type);
	
}

4) ConcreteAggregate role

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 cursor; //定义游标

		public ChannelIteratorImpl(ChannelTypeEnum ty,
				List<Channel> channelsList) {
			this.type = ty;
			this.channels = channelsList;
		}

		@Override
		public boolean hasNext() {
			//通过比较大小来实现
			while (cursor < channels.size()) {
				Channel c = channels.get(cursor);
				if (c.getTYPE().equals(type) || type.equals(ChannelTypeEnum.ALL)) {
					return true;
				} else
					cursor++;
			}
			return false;
		}

		@Override
		public Channel next() {
			Channel c = channels.get(cursor);
			cursor++;
			return c;
		}

		@Override
		public boolean isLast() {
			if(cursor==(channels.size()-1)){
				return true;
			}
			return false;
		}
	}
}

5) client

public class Client {

	public static void main(String[] args) {
		//新建集合,并添加频道(1-6频道)
		ChannelCollection channels = new ChannelCollectionImpl();
		channels.addChannel(new Channel(1,ChannelTypeEnum.CCTV1));
		channels.addChannel(new Channel(2,ChannelTypeEnum.CCTV2));
		channels.addChannel(new Channel(3,ChannelTypeEnum.CCTV3));
		channels.addChannel(new Channel(4,ChannelTypeEnum.JXTV1));
		channels.addChannel(new Channel(5,ChannelTypeEnum.JXTV2));
		channels.addChannel(new Channel(6,ChannelTypeEnum.JXTV2));
		
		//遍历所有频道
		ChannelIterator iterator = channels.iterator(ChannelTypeEnum.ALL);
		while(iterator.hasNext()){
			Channel channel = iterator.next();
			System.out.println(channel.toString());
			if(iterator.isLast()){
				System.out.println("我是最后一个了---------------");
			}
		}
		
		System.out.println("遍历指定的频道---------------");
		//发现有两个JXTV1,只遍历JXTV2
		ChannelIterator jxtv1 = channels.iterator(ChannelTypeEnum.JXTV2);
		while(jxtv1.hasNext()){
			Channel channel = jxtv1.next();
			System.out.println(channel.toString());
		}
		
	}
	
}

Case effect:

1.4. Summary and Suggestions

    The iterator pattern is implemented by separating the traversal behavior of the aggregate object and abstracting it into an iterator class. Its purpose is to allow external code to transparently access the internal data of the aggregate without exposing the internal structure of the aggregate object.

Application scenario:

    1) If you want to provide a standard method to iterate the collection and hide the implementation logic of the client program, you can use the iterator mode;

    2) When you need to provide a unified interface for traversing different aggregation structures, you can use the iterator mode.

Application of iterator mode in JDK:

    Collection subclass

    java.util.Scanner

Guess you like

Origin blog.csdn.net/xiaoxianer321/article/details/125401780