Kim-Baek 개발자 이야기

디자인패턴 - 비지터 패턴 본문

컴퓨터 공학/자료구조, 알고리즘

디자인패턴 - 비지터 패턴

김백개발자 2023. 7. 7. 17:44

 

디자인 패턴 중, 비지터 패턴에 대해서 강의를 듣고 정리해보았다. 

위의 다이어그램이 비지터 패턴의 다이어그램이다. 중요한 것은 Element( 자료구조 ) 는 변화하지 않는다는 것과 vistor ( 서비스 로직 ) 가 추가되는 기능을 가진다는 것이다.

비지터 패턴은 일반적으로 프로그래밍을 하는 과정에서 생각하는 것과는 약간 다른데, 아래와 같다고 보면 된다.

일반적 : 방문자는 “구매” 라는 기능을 가지고 가게에 간다. 버거킹에 가면 “햄버거”를 사고, 피자헛에 가면 “피자"를 산다.

비지터패턴 : 가게에 방문자가 들어간다. 가게가 방문자에게 자신의 정보를 주고, 방문자는 정보에 따라 “버거킹의 햄버거 구매”, “피자헛의 피자 구매” 라는 기능을 호출한다.

 

코드 예시를 통해서 살펴보도록 하자. 비지터 패턴이 적용되기 전이다.

public interface Shape {

    void printTo(Device device);

}


public class Rectangle implements Shape {

    @Override
    public void printTo(Device device) {
        if (device instanceof Phone) {
            System.out.println("print Rectangle to phone");
        } else if (device instanceof Watch) {
            System.out.println("print Rectangle to watch");
        }
    }
}


public class Client {

    public static void main(String[] args) {
        Shape rectangle = new Rectangle();
        Device device = new Phone();
        rectangle.printTo(device);
    }
}

위의 코드에서 하고 싶은 것은 Shape 가 Device 를 받아서 출력을 하고 싶다는 것이다. 그런데 문제가 있다.

-> Device 가 늘어나면, 각 Shape 마다 if / else 가 추가되는 문제이다!

여기서 이 코드를 보면 살짝 어색하다고 느낄 수 있다. 내가 만약에 코드를 짠다면, 아래와 같이 반대로 했을 것 같다.

위의 코드와 같이 Device 가 Shape 를 받아서 출력하도록 작성했다.

내가 작성한 코드는 어떤 경우에 좋을까? Shape 라는 자료구조가 계속 늘어날 때 좋다. 오각형, 육각형 계속 늘어난다면 Device 의 변화없이 자료구조만 늘어나게 된다.

하지만 비지터 패턴을 쓰게 되는 경우는 그 반대라고 생각하면 된다. 자료구조의 변경이 싫고, 알고리즘의 추가가 되는 경우이다.

Shape 를 변경하고 싶지 않은경우가 뭘까? ( 참고 : https://refactoring.guru/ko/design-patterns/visitor

  • ex) Shape 의 면적을 출력하는 기능이 필요하다고 해보자
  • Shape 에 getArea 를 추가해서, Device 에서 호출하는 식으로 개발이 될 것이다.
  • 그런데 Shape 에 오류가 생길 것 같아서, 추가하고 싶지 않다. + 또 새로운 기능이 있으면 계속 코드 바꿀꺼야?

이런 경우에 자료구조의 정보를 넣어줄테니, 알아서 비지터에서 처리해라! 가 될 수 있다.

Shape (자료구조) 는 비지터를 받는 메소드 하나만 가지게 된다.

그리고 구현체에서는 device 의 비지터메소드 ( 여기서는 print ) 에 자기 자신을 넣어주게 된다. 이 의미는 내 정보를 넣어줄테니 너가 알아서 처리해라. 라고 볼 수 있다.

그리고 여기서 Dispatch ( 다형성 ) 이 한번 이뤄지는 데, device 는 인터페이스인데, 어떤 구체 클래스 print 메소드 인지 찾는다. ( visit 메소드 ) 

그리고 Visitor 는 이제 각 자료구조마다 어떤 행동을 할지 인터페이스에서 정의한다.

그리고 구현체마다 이것들을 구현해서 사용하게 된다. 이렇게 되면 Visitor 를 새로 만들어서 Element (자료구조) 에 주기만 하면, Visitor 에서 정보를 받아서 알아서 처리할 수 있게 된다.

클라이언트 코드에서도 한번의 dispatch 가 더 일어나는데,  "accept 는 인터페이스에 정의된 메소드인데, 어떤 구체 클래스 ( Shape 의 ) 인지 찾는다." 가 Dispatch 이다.

 

비지터 패턴은 자료구조의 변경이 어려울 때, 서비스 로직이 계속 추가될 때 쓴다.

 

반응형
Comments