Java

[Design Pattern] 반복자 패턴(Iterator Pattern)

구루싸 2020. 6. 8. 22:30
반응형
SMALL

아직 6월 초인데
한 여름 마냥
날씨가 급격하게 더워져서

출퇴근 길에 땀이 흥건...하...
30도 가까이 되는 지역도 있더라고요
코로나19도 끝날 기미가 보이지 않는데
몸 관리 잘하시길 바랍니다

아무튼 오늘의 학습 주제는 

디자인 패턴(Design Patter) 중

반복자 패턴(Iterator Pattern)입니다

반복자 패턴이란

무엇인가 많이 모여 있는 것(집합체)들을

순서대로 지정하면서 전체를 검색하기 위한

디자인 패턴을 말합니다

아래의 표는 반복자 패턴을 구성하는

역할들을 정리한 것입니다

역할설명
반복자(Iterator)요소를 순서대로 검색해가는 인터페이스를 결정
구체적인 반복자(Concrete Iterator)반복자(Iterator)가 결정한 인터페이스를 실제로 구현
집합체(Aggregate)반복자(Iterator) 역할을 만들어내는 인터페이스를 결정
구체적인 집합체(Concrete Aggregate)집합체(Aggregate) 역할이 결정한 인터페이스를 실제로 구현

표만 봐서는 무슨 말인지 모르겠습니다-_-

실제로 구현을 해보면 아래와 같습니다

1. 인터페이스(Interface) Iterator.java

package IteratorPattern;

public interface Iterator {
	public abstract boolean hasNext();
	public abstract Object next();
}

2. 인터페이스(Interface) Aggregate.java

package IteratorPattern;

public interface Aggregate {
	public abstract Iterator iterator();
}

3. 클래스(Class) Book.java

package IteratorPattern;

public class Book {
	private String name;
	public Book(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
}

4. 클래스(Class) BookShelf.java

package IteratorPattern;

public class BookShelf implements Aggregate {
	private Book[] books;
	private int last = 0;
	public BookShelf(int maxsize) {
		this.books = new Book[maxsize];
	}
	public Book getBookAt(int index) {
		return books[index];
	}
	public void appendBook(Book book) {
		this.books[last++] = book;
	}
	public int getLength() {
		return last;
	}
	public Iterator iterator() {
		return new BookShelfIterator(this);
	}
}

5. 클래스(Class) BookShelfIterator.java

package IteratorPattern;

public class BookShelfIterator implements Iterator {
	private BookShelf bookShelf;
	private int index;
	public BookShelfIterator(BookShelf bookShelf) {
		this.bookShelf = bookShelf;
		this.index = 0;
	}
	public boolean hasNext() {
		if ( index < bookShelf.getLength() ) {
			return true;
		} 
		return false;
	}
	public Object next() {
		Book book = bookShelf.getBookAt(index++);
		return book;
	}
}

6. 클래스(Class) Test.java

import IteratorPattern.*;

public class Test {
	public static void main(String[] args) {
		/* Iterator Pattern */
		BookShelf bookShelf = new BookShelf(4);
		bookShelf.appendBook(new Book("Around the World in 80 Days"));
		bookShelf.appendBook(new Book("Bible"));
		bookShelf.appendBook(new Book("Cinderella"));
		bookShelf.appendBook(new Book("Daddy-Long-Legs"));
		Iterator it = bookShelf.iterator();
		while ( it.hasNext() ) {
			Book book = (Book)it.next();
			System.out.println(book.getName());
		}
	}
}

위의 코드를 간단히 설명하자면

Book 객체를 관리하는 BookShelf 객체가 있고

이 BookShelf 객체는 Iterator를 지원합니다

구체적인 Iterator는
BookShelfIterator 객체가 수행합니다

반복자 패턴을 사용하는 이유는 무엇일까요?

그 이유는 구현에 상관 없이

반복자를 사용할 수 있기 때문입니다

자바의 추상클래스나 인터페이스를

사용하는 이유이기도 한데요

해당 클래스 내부가 변경되어도

실 사용자(여기서는 Test 클래스)는

hasNext()와 next() 메소드만을
사용하면 되기 때문에

반복문을 변경을 하지 않아도 된다는 점입니다

예를 들어서 배열에 저장하지 않고

아래와 같이 ArrayList에 저장한다든지...

7. 클래스(Class) 변경한 BookShelf.java

package IteratorPattern;

import java.util.ArrayList;

public class BookShelf implements Aggregate {
	private ArrayList<Book> books;
	public BookShelf() {
		this.books = new ArrayList<Book>();
	}
	public Book getBookAt(int index) {
		return books.get(index);
	}
	public void appendBook(Book book) {
		this.books.add(book);
	}
	public int getLength() {
		return books.size();
	}
	public Iterator iterator() {
		return new BookShelfIterator(this);
	}
}

물론 hasNext()와 next()의 구현은
제대로 되어야겠죠-_-

위의 구현은 매우 간단하게

앞에서부터 차례대로 검색하지만

역방향으로 진행하거나 점프를 하는 등의

구현도 가능합니다

8. 인터페이스(Interface) 변경한 Iterator.java

package IteratorPattern;

public interface Iterator {
	public abstract boolean hasNext();
	public abstract Object next();
	public abstract boolean hasPrevious();
	public abstract Object previous();
}

9. 클래스(Class) 변경한 BookShelfIterator.java

package IteratorPattern;

public class BookShelfIterator implements Iterator {
	private BookShelf bookShelf;
	private int next;
	private int previous;
	public BookShelfIterator(BookShelf bookShelf) {
		this.bookShelf = bookShelf;
		this.next = 0;
		this.previous = bookShelf.getLength() - 1;
	}
	public boolean hasNext() {
		if ( next < bookShelf.getLength() ) {
			return true;
		} 
		return false;
	}
	public Object next() {
		Book book = bookShelf.getBookAt(next++);
		return book;
	}
	public boolean hasPrevious() {
		if ( -1 < previous ) {
			return true;
		} 
		return false;
	}
	public Object previous() {
		Book book = bookShelf.getBookAt(previous--);
		return book;
	}
}

10. 클래스(Class) 변경한 Test.java

import IteratorPattern.*;

public class Test {
	public static void main(String[] args) {
		/* Iterator Pattern */
		BookShelf bookShelf = new BookShelf();
		bookShelf.appendBook(new Book("Around the World in 80 Days"));
		bookShelf.appendBook(new Book("Bible"));
		bookShelf.appendBook(new Book("Cinderella"));
		bookShelf.appendBook(new Book("Daddy-Long-Legs"));
		Iterator it = bookShelf.iterator();
		while ( it.hasNext() ) {
			Book book = (Book)it.next();
			System.out.println(book.getName());
		}
		while ( it.hasPrevious() ) {
			Book book = (Book)it.previous();
			System.out.println(book.getName());
		}
	}
}

 

 

반복자 인터페이스 Iterator에

hasPrevious()와 previous()를 추가해주고

Iterator를 implements한 클래스
BookShelfIterator에

hasPrevious()와 previous()를
구현하였습니다

기능이 추가되었기에 클래스
Test에서 테스트해보면

아까와 반대의 순서로 출력되는 것을
확인할 수 있습니다

아래에 반복자 패턴의
클래스 다이어그램을 첨부하고

오늘의 학습을 마치겠습니다

그럼 이만-_-

 

 

 

 

 

반응형
LIST