<디자인패턴입문> 10. Visitor 패턴
by BFinewww.yes24.com/Product/Goods/2918928
가. 무엇인가
a. 똑똑~
- 많은 요소가 있을때 각 요소에 대한 처리 코드는 어디에 있을까?
- 일반적으로는 데이터 구조를 표시하고 있는 클래스에 기술한다.
=> 처리가 여러종류라면 새로운 처리가 필요할때마다 데이터 구조의 클래스를 수정해야한다.
- 위와 다르게 방문자 패턴은 방문자 클래스에게 처리를 위임하는 것이다.
=> 새로운 처리를 추가하고 싶으면 새로운 방문자를 만들면 되고 요소는 방문자를 받아들이면 된다.
나. 만들어본 예제
a. Visitor (방문자) 역할
- 구체적인 요소 (ConcreteElement) 마다 visit(요소)를 명세한 인터페이스
- Visitor를 통일 시켜주는 역할을 한다.
public interface Visitor {
int visit(WorkBook workBook);
int visit(NovelBook novelBook);
}
b. ConcreteVisitor (구체적인 방문자) 역할
- 각각의 특성에 맞게 모든 구체적인 요소의 처리를 구현한다.
- 예제에서는 회원, 비회원별 책 종류에 따른 할인된 가격을 반환하는 처리를 한다.
public class GuestVisitor implements Visitor{
@Override
public int visit(WorkBook workBook) {
return (int) (workBook.getPrice()*0.95);
}
@Override
public int visit(NovelBook novelBook) {
return (int) (novelBook.getPrice()*0.99);
}
}
public class MemberVisitor implements Visitor{
@Override
public int visit(WorkBook workBook) {
return (int) (workBook.getPrice()*0.90);
}
@Override
public int visit(NovelBook novelBook) {
return (int) (novelBook.getPrice()*0.95);
}
}
c. Element(요소) 역할
- Visitor 역할을 받는 메서드를 명세하는 인터페이스
public interface Book {
int accpetPrice(Visitor visitor);
}
d. ConcreteElement(구체적 요소) 역할
- Element 역할의 인터페이스를 구체적으로 구현한다.
- 인터페이스를 구현하는 메서드는 방문자를 받아들이는 것을 의미한다.
public class WorkBook implements Book{
Map<String, Integer> store = new WeakHashMap<String, Integer>();
{
store.put("영어문법",15000);
store.put("수리가형문제집",10000);
store.put("한국사100제",30000);
}
private int price;
public WorkBook(String bookName) {
this.price = store.get(bookName);
}
@Override
public int accpetPrice(Visitor visitor) {
return visitor.visit(this) ;
}
public int getPrice() {
return this.price;
}
}
public class NovelBook implements Book{
Map<String, Integer> store = new WeakHashMap<String, Integer>();
{
store.put("어린왕자",12000);
store.put("노인과바다",50000);
store.put("오늘하루",17000);
}
private int price;
public NovelBook(String name) {
this.price = store.get(name);
}
@Override
public int accpetPrice(Visitor visitor) {
return visitor.visit(this);
}
public int getPrice() {
return price;
}
}
e. Main
public class Main {
public static void main(String[] args) {
NovelBook novelBook = new NovelBook("노인과바다");
int guestPrice = novelBook.accpetPrice(new GuestVisitor());
int memberPrice = novelBook.accpetPrice(new MemberVisitor());
System.out.println("소설 회원가 : "+ memberPrice);
System.out.println("소설 비회원가 : "+guestPrice );
WorkBook workBook = new WorkBook("수리가형문제집");
guestPrice = workBook.accpetPrice(new GuestVisitor());
memberPrice = workBook.accpetPrice(new MemberVisitor());
System.out.println("문제집 회원가 : "+ memberPrice);
System.out.println("문제집 비회원가 : "+guestPrice );
}
}
/**
"C:\Program Files\Java\jdk-11.0.8\bin\java.exe"
소설 회원가 : 47500
소설 비회원가 : 49500
문제집 회원가 : 9000
문제집 비회원가 : 9500
*/
다. 정리
a. 더블 디스패치
- element.accept(Visitor) 이고 visitor.visit(element) 를 보면 서로 정확인 반대의 관계인 것을 볼 수있다.
- 이렇게 한쌍에 의해 처리되는 것을 더블 디스패치(이중분리) 라고한다.
b. 왜 이렇게 복잡하게 할까?
- Visitor 패턴의 목적은 처리를 데이터 구조에서 분리하는 일이다.
- 즉 Visitor 패턴은 위의 NovelBook, WorkBook 요소를 부품으로써 독립성을 높일 수 있다는 장점이 있다.
c. Visitor 추가는 간단!, Element 추가는 곤란;;
- 위의 예제에서 처럼 Visitor(처리)는 간단하게 새로운 클래스를 생성해주기만 하면 된다.
- Element를 추가할경우 모든 Visitor에 추가 내용들을 기술해야하는 문제가 있다.
Visitor 패턴은 요소들에 대한 처리를 Visitor에게 위임하여 처리를 분리하는 패턴이다.
'개발서적 > 디자인패턴입문' 카테고리의 다른 글
<디자인패턴입문> 12. Facade 패턴 (0) | 2021.05.05 |
---|---|
<디자인패턴입문> 11. Chain of Responsibility 패턴 (0) | 2021.05.04 |
<디자인패턴입문> 9. Decorator 패턴 (0) | 2021.05.02 |
<디자인패턴입문> 8. Composite 패턴 (0) | 2021.05.01 |
<디자인패턴입문> 7. Strategy 패턴 (0) | 2021.04.30 |
블로그의 정보
57개월 BackEnd
BFine