박은종의 객체지향 설계를 위한 디자인패턴 with 자바
구조안을 돌아다니며 처리하는 패턴(Iterator, Vsitor, Chain of responsibility)
Iterator
객체 요소들의 내부 표현방식을 공개하지 않고, 객체에서 되지 않은, 외부에서 객체에 순회하는 객체를 만든다.
- 내부에서 객체의 순차적인 제공을 하지 않음
- 순회 구현 방식이 다르더라도 동일한 방식(메서드)로 순회 할 수 있게 제공
- 여러 리스트 객체에 대한 동일한 방식으로 순회하는 방법을 제공하기 위해 순회하는 객체를 따로만듬
- ConcreteIterator는 리스트를 순회하면서 각 리스트의 요소를 반환하는 메서드도 제공한다.
- 다양한 순회방법이 제공될 수 있다.
- 동일한 Aggregate를 구현한 클래스들은 동일한 방식으로 순회할 수 있다.
package com.backend.bakckend.designpattern.state;
interface Iterator {
boolean hasNext();
Object next();
}
interface Aggregate {
public abstract Iterator iterator(int type);
public int getLength();
}
class Book {
private String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class Constant {
public static final int FORWARD = 0;
public static final int REVERSE = 1;
}
abstract class Factory {
public final Iterator create(Aggregate list, int type) {
Iterator iterator = createProduct(list, type);
return iterator;
}
protected abstract Iterator createProduct(Aggregate list, int type);
}
class BookShelf implements Aggregate {
private Book[] books;
private int last = 0;
Factory f = ItertorFactory.getInstance();
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;
last++;
}
public int getLength() {
return last;
}
public Iterator iterator(int type) {
if (type == 0) {
return new BookShelfIterator(this);
} else {
return new BookShelfReverseIterator(this);
}
}
}
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;
} else {
return false;
}
}
public Object next() {
Book book = bookShelf.getBookAt(index);
index++;
return book;
}
}
class ItertorFactory extends Factory {
private static ItertorFactory factory = new ItertorFactory();
private ItertorFactory() {
}
public static ItertorFactory getInstance() {
if (factory == null) {
factory = new ItertorFactory();
}
return factory;
}
@Override
protected Iterator createProduct(Aggregate list, int type) {
if (type == Constant.FORWARD) {
return new BookShelfIterator((BookShelf) list);
} else {
return new BookShelfReverseIterator((BookShelf) list);
}
}
}
class BookShelfReverseIterator implements Iterator {
private BookShelf bookShelf;
private int index;
public BookShelfReverseIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
this.index = bookShelf.getLength() - 1;
}
public boolean hasNext() {
if (index >= 0) {
return true;
} else {
return false;
}
}
public Object next() {
Book book = bookShelf.getBookAt(index);
index--;
return book;
}
}
public class IteratorTest {
public static void main(String[] args) {
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(Constant.FORWARD);
while (it.hasNext()) {
Book book = (Book) it.next();
System.out.println("" + book.getName());
}
System.out.println("============");
it = bookShelf.iterator(Constant.REVERSE);
while (it.hasNext()) {
Book book = (Book) it.next();
System.out.println("" + book.getName());
}
}
}
Vsitor
- 구조 안을 돌아다니며 일을 함 "방문자"
- 객체 구조의 요소들이 수행해야할 기능을 모아둔 패턴
- 각 객체 요소를 변경하지 않고, 기능을 추가할 수 있음
- 데이터의 구조와 처리를 분리하여 처리하는 부분을 객체로 만들어 각 데이터 구조를 돌아다니며 오퍼레이션이 수행되도록 함
- 각 데이터는 이러한 visitor를 accept 함
- 추상구문 트리의 예
- 문법적 처리를 위해 각 노드마다 수행해야 하는 기능을 따로 정의 해야함
- 여러 요소에 대해 유사한 기능의 메서드를 한곳에 모아서 관리하게 되고, 여러 클래스에 걸친 메서드를 추가하기 용이함
- 각 클래스에 대한 기능이 자주 변경되거나 알고리즘의 변화가 많을때 사용하는것이 효율적임
- 새로운 요소 클래스를 추가하게 되면 그에 해당되는 기능을 모든 Visitor에서 구현해하 함
- 따라서 요소의 변화가 거의 없고 기능의 추가 삭제가 자주 발생할때 사용하는것이 좋음
- 각 객체의 오퍼레이션이 외부에 노출되는 것이므로 객체지향 프로그래밍의 캡슐화 전략에 위배
- 주로 Composite 패턴에서 자주 사용될 수 있음
Chain of responsibility
- 책임 떠넘기기
- 다수의 객체를 사슬처럼 연결
- 요청을 처리할 수 있는 기회를 하나 이상의 객체에게 부여함
- 요청을 해결할 객체를 만날 때까지 객체 고리를 따라서 요청을 전달
- 메세지를 보내는 객체와 이를 받아서 처리하는 객체들 간의 결합도를 줄이기 위함
- 하나의 요청에 대한 처리가 반드시 한 객체에서만 이루어지는것이 아닌 여러 객체가 조건이 맞으면 처리의 기회를 가지게 됨
- HELP 시스템 같은 경우 적절한 답을 찾을 때 까지 연결되어 해결할 수 있음
- 객체들 간의 결합도가 적어진다. 요청을 처리하는 객체와 요청을 보내는 객체가 서로 모를 수 있다.
- 연결순서는 상황에 따라 바뀌거나 추가 삭제될 수 있다. 즉 객체의 책임을 추가, 변경, 확장할 수 있다.
- 메세지가 항상 수신된다는것을 보장할 수 없다.
LIST
'4차산업혁명의 일꾼 > 웹개발' 카테고리의 다른 글
디자인 패턴 with 자바 - 낭비를 없애기(Flyweight, Proxy) (0) | 2023.03.09 |
---|---|
스프링 부트의 정석 : 이번에도 남궁성과 끝까지 간다 1 (0) | 2023.03.06 |
복잡한 연결을 단순하고 간단하게 처리하는 패턴(Facade, Mediator) (0) | 2023.03.06 |
(State, Observer, Memento:상태저장)상태를 클래스로 표현하여 관리하는 패턴 (0) | 2023.03.05 |
디자인패턴 5 : Adapter Pattern(호환) (0) | 2023.03.04 |