비지터 패턴은 실제로 구조체(struct)를 수정하지 않고도 구조체에 행동을 추가할 수 있도록 합니다. 당신이 다음과 같은 다른 모양들의 구조체(structs)들을 가진 lib의 관리자라고 가정해 봅시다:
직사각형
원
삼각형
위의 각 모양의 구조체(struct)는 공통 모양 인터페이스를 구현합니다.
회사 사원들이 당신의 멋진 lib을 사용하기 시작하면 그들은 여러 기능들을 요청할 것입니다. 이 중 가장 간단한 요청을 검토해 봅시다: 회사 부서가 모양 구조체들에 getArea(면적 가져오기) 행동을 추가해달라고 요청했습니다.
이 문제를 해결하기 위한 여러 옵션이 있습니다.
가장 먼저 떠오르는 옵션은 getArea 메서드를 모양 인터페이스에 직접 추가한 다음 각 모양 구조체(struct)에서 구현하는 것입니다. 좋은 옵션인 듯싶으나 단점이 있습니다. 당신은 라이브러리의 관리자로서 누군가가 다른 행동을 요청할 때마다 당신의 귀중한 코드가 손상되는 위험을 감수하고 싶지 않을 것입니다. 그럼에도 불구하고 당신은 다른 팀들이 당신의 라이브러리를 어떻게든 확장하기를 원합니다.
두 번째 옵션은 기능을 요청하는 부서가 직접 행동을 구현하도록 하는 것이나 요청된 행동은 비공개 코드에 의존할 수 있으므로 항상 가능한 옵션이 아닙니다.
세 번째 옵션은 비지터 패턴을 사용하여 위의 문제를 해결하는 것이며, 다음과 같이 비지터 인터페이스를 정의하는 것으로 시작합니다:
visitForSquare(square), visitForCircle(circle), visitForTriangle(triangle) 함수들은 사각형, 원 및 삼각형에 각각 기능들을 추가할 수 있도록 합니다.
비지터 인터페이스에 단일 메서드 visit(shape)가 있을 수 없는 이유가 궁금하나요? 그 이유는 Go 언어가 메서드 오버로딩을 지원하지 않기 때문에 이름은 같지만 매개변수들이 다른 메서드들을 가질 수 없도록 하기 때문입니다.
이제 두 번째 중요한 부분은 모양 인터페이스에 accept 메서드를 추가하는 것입니다.
모든 모양 구조체들(structs)은 이 메서드를 정의해야 하며, 코드는 다음과 비슷하게 작성됩니다:
잠시만요, 방금 기존 모양 구조체들(structs)을 수정하고 싶지 않다고 언급하지 않았나요? 불행히도 비지터 패턴을 사용할 때 모양 구조체를 수정해야 하긴 합니다. 그러나 이 수정은 단 한 번만 수행됩니다.
getNumSides와 getMiddleCoordinates같은 다른 행동들을 추가하는 경우 우리는 모양 구조체들(structs)에 추가 변경 없이 같은 accept(visitor) 함수를 사용합니다.
최종적으로 모양 구조체들(structs)은 한 번만 수정하면 되며, 다른 행동들을 추가해 달라는 모든 향후 요청은 같은 accept 함수를 사용하여 처리할 수 있습니다. 팀에서 getArea 행동을 요청하면 단순히 비지터 인터페이스의 구상 구현을 정의한 후 해당 구현에 면적 계산 로직을 작성하여 요청된 행동을 추가할 수 있습니다.