Volver a aprender patrones de diseño (3. Patrones de diseño-patrones iteradores)

1. Modo iterador

    A partir de JDK1.2, se introduce una interfaz Iterator:

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

    Todos aquellos que implementan la interfaz Iterator contienen un Iterator<E> iterator()método que hace que la persona que llama desconozca qué clase crea una instancia del objeto iterado.

    Iterator (Iterador) es muy utilizado en las colecciones Java, con las que deberíamos estar más familiarizados, proporciona un método de acceso secuencial a cada elemento del contenedor. Este es el patrón de iterador que vamos a aprender hoy.

1.1, ¿cuál es el modo iterador?

  • definición

    El patrón Iterator es un patrón de diseño de comportamiento que proporciona un objeto para acceder secuencialmente a una serie de datos en un objeto agregado, sin exponer la representación interna del objeto agregado (lista, pila, árbol...) para recorrer los elementos de la colección.

    El patrón de iterador no es solo atravesar una colección, podemos proporcionar diferentes tipos de iteradores según nuestras necesidades. Sin embargo, rara vez implementamos un iterador por nosotros mismos, y el iterador proporcionado en la API de Java es completamente suficiente.

La estructura del iterador:

    1) Rol de agregación abstracta (Agregado): define la interfaz para almacenar, agregar, eliminar objetos agregados y crear objetos iteradores;

    2) Función ConcreteAgregate: implementa una clase agregada abstracta y devuelve una instancia de un iterador concreto;

    3) Rol de iterador abstracto (Iterator): define la interfaz para acceder y atravesar elementos agregados, que generalmente incluye hasNext(), first(), next() y otros métodos;

    4) Implementar el método definido en la interfaz del iterador abstracto, completar el recorrido del objeto agregado y registrar la posición actual del recorrido.

    La intención del patrón Iterator es proporcionar una forma de acceder a los elementos de un objeto agregado sin exponer su representación subyacente.

1.2 Ventajas y desventajas del modo iterador

  • ventaja

    1) De acuerdo con el principio de responsabilidad única, el gran algoritmo transversal se puede extraer en una clase separada para limpiar el código del cliente y la colección.

    2) De acuerdo con el principio de apertura y cierre, podemos implementar nuevos tipos de colecciones e iteradores de acuerdo con nuestras propias necesidades sin modificar el código original.

    3) Tiene una buena encapsulación y proporciona una interfaz unificada para atravesar diferentes estructuras de agregación.

  • defecto

    1) Si se trata de una colección relativamente simple, usar el modo iterador puede ser una exageración;

    2) Usar un iterador puede ser menos eficiente que atravesar directamente los elementos de alguna colección especializada.

1.3 Método de creación

    Tomemos los canales de TV como ejemplo y escribamos un iterador personalizado.

1) Cree una nueva clase POJO de canal (objeto Java ordinario simple-objeto Java simple)

//先声明我们的频道枚举
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) Rol de iterador abstracto (Iterador)

public interface ChannelIterator {

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

3) Rol de agregación abstracta (agregado)

public interface ChannelCollection {

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

4) Rol de ConcreteAgregate

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) cliente

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());
		}
		
	}
	
}

Efecto de caso:

1.4 Resumen y sugerencias

    El patrón de iterador se implementa separando el comportamiento transversal del objeto agregado y abstrayéndolo en una clase de iterador. Su propósito es permitir que el código externo acceda de manera transparente a los datos internos del agregado sin exponer la estructura interna del objeto agregado.

Escenario de aplicación:

    1) Si desea proporcionar un método estándar para iterar la colección y ocultar la lógica de implementación del programa cliente, puede usar el modo iterador;

    2) Cuando necesite proporcionar una interfaz unificada para atravesar diferentes estructuras de agregación, puede usar el modo iterador.

Aplicación del modo iterador en JDK:

    Subclase de colección

    java.util.Escáner

Supongo que te gusta

Origin blog.csdn.net/xiaoxianer321/article/details/125401780
Recomendado
Clasificación