Iterator Ontwerppatroon in Java

Iterator ontwerppatroon is een van de gedragspatronen. Het iteratorpatroon wordt gebruikt om een ​​standaard manier te bieden om door een groep objecten te navigeren. Het iteratorpatroon wordt veel gebruikt in de Java Collection Framework. De Iterator-interface biedt methoden om door een verzameling te navigeren.

Iterator Ontwerppatroon

Volgens GoF is het doel van het iterator-ontwerppatroon:

Biedt een manier om toegang te krijgen tot de elementen van een samengesteld object zonder de onderliggende representatie bloot te leggen.

Het iteratorpatroon gaat niet alleen over het doorlopen van een verzameling, we kunnen verschillende soorten iterators bieden op basis van onze vereisten. Het iteratorontwerppatroon verbergt de daadwerkelijke implementatie van de navigatie door de verzameling en clientprogramma’s gebruiken alleen de iterator-methoden.

Voorbeeld van het Iterator-patroon

Laten we het iteratorpatroon begrijpen aan de hand van een eenvoudig voorbeeld. Stel dat we een lijst hebben van radiokanalen en het clientprogramma wil er één voor één doorheen gaan of op basis van het type kanaal. Bijvoorbeeld, sommige clientprogramma’s zijn alleen geïnteresseerd in Engelse kanalen en willen alleen deze verwerken, ze willen andere soorten kanalen niet verwerken. Dus we kunnen een verzameling kanalen aan de client geven en hen de logica laten schrijven om door de kanalen te bladeren en te beslissen of ze moeten worden verwerkt. Maar deze oplossing heeft veel problemen, zoals dat de client de logica voor het doorlopen moet bedenken. We kunnen er niet zeker van zijn dat de logica van de client juist is. Bovendien wordt het erg moeilijk te onderhouden als het aantal clients groeit. Hier kunnen we het iteratorpatroon gebruiken en iteratie bieden op basis van het type kanaal. We moeten ervoor zorgen dat het clientprogramma alleen toegang heeft tot de lijst met kanalen via de iterator. Het eerste deel van de implementatie is het definiëren van het contract voor onze collectie- en iteratorinterfaces. ChannelTypeEnum.java

package com.journaldev.design.iterator;

public enum ChannelTypeEnum {

	ENGLISH, HINDI, FRENCH, ALL;
}

ChannelTypeEnum is een Java-enum die alle verschillende soorten kanalen definieert. 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 is een eenvoudige POJO-klasse met de attributen frequentie en kanaaltype. 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);
	
}

De ChannelCollection-interface definieert het contract voor onze implementatie van de verzamelingsklasse. Let op dat er methoden zijn om een kanaal toe te voegen en te verwijderen, maar er is geen methode die de lijst met kanalen retourneert. ChannelCollection heeft een methode die de iterator retourneert voor traversering. De ChannelIterator-interface definieert de volgende methoden; `ChannelIterator.java`

package com.journaldev.design.iterator;

public interface ChannelIterator {

	public boolean hasNext();
	
	public Channel next();
}

Nu onze basisinterface en kernklassen klaar zijn, laten we doorgaan met de implementatie van de verzamelingsklasse en iterator. `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;
		}

	}
}

Let op de implementatie van de binnenklasse van de iterator-interface zodat de implementatie niet kan worden gebruikt door een andere verzameling. Dezelfde aanpak wordt ook gevolgd door verzamelingsklassen en ze hebben allemaal een binnenklasse-implementatie van de Iterator-interface. Laten we een eenvoudig testprogramma voor het iteratorpatroon schrijven om onze verzameling en iterator te gebruiken om door de verzameling van kanalen te traverseren. `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("******");
		// Kanaaltype 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;
	}

}

Wanneer ik het bovenstaande programma uitvoer, produceert het de volgende output;

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

Belangrijke punten van het iteratorontwerppatroon

  • Het iteratorpatroon is handig wanneer u een standaardmanier wilt bieden om door een verzameling te itereren en de implementatielogica wilt verbergen voor het clientprogramma.
  • De logica voor iteratie is ingebed in de collectie zelf en het helpt het clientprogramma om er gemakkelijk overheen te itereren.

Iterator-ontwerppatroon in JDK

We weten allemaal dat de Iterator van het Collection Framework het beste voorbeeld is van de implementatie van het iteratorpatroon, maar weet je dat de klasse java.util.Scanner ook de Iterator-interface implementeert? Lees deze post om meer te weten te komen over Java Scanner Class. Dat is alles voor het iterator-ontwerppatroon, ik hoop dat het nuttig en gemakkelijk te begrijpen is.

Source:
https://www.digitalocean.com/community/tutorials/iterator-design-pattern-java