You will be fine

<디자인패턴입문> 10. Visitor 패턴

by BFine
반응형

www.yes24.com/Product/Goods/2918928

 

Java 언어로 배우는 디자인 패턴 입문

이 책은 디자인 패턴의 입문서입니다. GoF가 정리한 23개의 디자인 패턴을 하나씩 다루면서 객체 지향을 잘 모르는 초보자도 이해하기 쉽도록 정리하고 있습니다. 단순한 이론이나 논리을 제시하

www.yes24.com

 

가. 무엇인가

 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에게 위임하여 처리를 분리하는 패턴이다.
반응형

블로그의 정보

57개월 BackEnd

BFine

활동하기