방문자 패턴은 알고리즘들을 그들이 작동하는 객체들로부터 분리할 수 있도록 하는 행동 디자인 패턴입니다.
알고리즘들을 그들이 작동하는 객체들로부터 분리한다라..

새로운 메서드를 기존 클래스에 통합하는 대신에 visitor라는 별도의 클래스에 배치하자
class ExportVisitor implements Visitor is
method doForCity(City c) { ... }
method doForIndustry(Industry f) { ... }
method doForSightSeeing(SightSeeing ss) { ... }
// …
해당 메서드를 정확히 어떻게 호출할 수 있을까? 특히 전체 그래프(foreach)를 다룰 때,
이 메서드들은 시그니처들이 다르므로 다형성을 사용할 수 없습니다.
for Each {
if (node instance of City)
exportVistor.doForCity((City) node)
if (node instance of Industry)
exportVisitor.doForIndustry((Industry) node)
}
이 방법은 번거로운 조건문 없이 객체에 적절한 메서드를 실행하는 것을 목표로합니다.
객체들은 자신의 클래스들을 알고 있으므로 비지터가 올바른 메서드를 선택할 수 있도록 할 수 있습니다.
foreach (Node node in graph)
node.accept(exportVisitor)
// City
class City is
method accept(Visitor v) is
v.doForCity(this)
// …
// Industry
class Industry is
method accept(Visitor v) is
v.doForIndustry(this)
// …
노드(Element) 안바꾼다면서 바꿨.... accept 추가했네..

// interface - element
interface Shape is
method move(x,y)
method draw()
method accept(v: Vistor)
// implement - concrete element
class Dot implements Shape is
method accept(v: Visitor) is
v.visitDot(this)
class Circle implements Shape is
// …
method accept(v: Visitor) is
v.visitCircle(this)
class Rectangle implements Shape is
// …
method accept(v: Visitor) is
v.visitRectangle(this)
class CompoundShape implements Shape is
// …
method accept(v: Visitor) is
v.visitCompoundShape(this)
// interface - visitor
interface Visitor is
method visitDot(d: Dot)
method visitCircle(c: Circle)
method visitRectangle(r: Rectangle)
method visitCompoundShape(cs: CompoundShape)
// implements - concrete visitor
class XMLExportVisitor implements Visitor is
method visitDot(d: Dot) is
// 점의 아이디와 중심 좌표를 내보냅니다.
method visitCircle(c: Circle) is
// 원의 아이디, 중심 좌표 및 반지름을 내보냅니다.
method visitRectangle(r: Rectangle) is
// 사각형의 아이디, 왼쪽 상단 좌표, 너비 및 높이를 내보냅니다.
method visitCompoundShape(cs: CompoundShape) is
// 모양의 아이디와 그 자식들의 아이디 리스트를 내보냅니다.
// 클라이언트 코드
class Application is
field allShapes: array of Shapes[]
method export() is
exportVisitor = new XMLExportVisitor()
foreach (shape in allShapes) do
shape.accept(exportVisitor)
accept 이 필요한 이유 더블 디스패치 아래서 한번 더 보자
foreach (shape in allShapes) do
shape.accept(exportVisitor)
allShapes에 Dot, Circle 등이 섞여 있지만 루프에서는 전부 Shape 타입으로 잡힘
컴파일러는 구체적으로 뭔지 모름
shape.accept(exportVisitor)를 호출하면 런타임에 shape의 실제 타입에 따라 해당 클래스의 accept가 호출,
예를 들어 실제로 Dot 객체라면
class Dot implements Shape is
method accept(v: Visitor) is
v.visitDot(this)
이 시점에서 Dot이 확정 이게 첫 번째 디스패치
accept 안에서 v.visitDot(this)를 호출하면, v의 실제 타입에 따라 어떤 visitDot이 실행될지 결정
v가 XMLExportVisitor라면
class XMLExportVisitor implements Visitor is
method visitDot(d: Dot) is
// 점의 아이디와 중심 좌표를 내보냅니다.
한번의 호출로는 shape, visitor 두 축을 동시에 결정할 수 없어서 두번의 호출로 각각 다형성을 적용
그래서 더블 디스패치..
그러니깐 accept 쪽에서 자기 자신을 this로 넘겨줘야
visitor에서 해당 구현된 shape의 데이터에 접근된다는건데 ..
