아직 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에서 테스트해보면
아까와 반대의 순서로 출력되는 것을
확인할 수 있습니다
아래에 반복자 패턴의
클래스 다이어그램을 첨부하고
오늘의 학습을 마치겠습니다
그럼 이만-_-
'Java' 카테고리의 다른 글
[Design Pattern] 빌더 패턴(Builder Pattern) (0) | 2020.06.15 |
---|---|
[Design Pattern] 싱글톤(Singleton) 패턴과 프로토타입(Prototype) 패턴 (0) | 2020.06.14 |
[Design Pattern] 팩토리 메소드 패턴(Factory Method Pattern) (0) | 2020.06.13 |
[Design Pattern] 템플릿 메소드 패턴(Template Method Pattern) (0) | 2020.06.11 |
[Design Pattern] 어댑터 패턴(Adapter Pattern) (0) | 2020.06.09 |