{{위키데이터 속성 추적}}
[[파일:Visitor pattern class diagram in LePUS3.gif|섬네일|right|300px|[[Lepus3|LePUS3]]에서의 비지터]]

[[객체 지향 프로그래밍]]과 [[소프트웨어 공학]]에서 '''비지터''' 패턴(visitor pattern; 방문자 패턴)은 [[알고리즘]]을 객체 구조에서 분리시키는 [[디자인 패턴]]이다. 이렇게 분리를 하면 구조를 수정하지 않고도 실질적으로 새로운 동작을 기존의 객체 구조에 추가할 수 있게 된다. [[개방-폐쇄 원칙]]을 적용하는 방법의 하나이다.

== 구조 ==
=== UML 클래스 및 시퀀스 다이어그램 ===
[[파일:w3sDesign Visitor Design Pattern UML.jpg|frame|none|비지터 디자인 패턴을 위한 샘플 UML 클래스와 시퀀스 다이어그램.<ref>{{웹 인용|title=The Visitor design pattern - Structure and Collaboration|url=http://w3sdesign.com/?gr=b11&ugr=struct|website=w3sDesign.com|accessdate=2017-08-12}}</ref>]]

=== 클래스 다이어그램 ===
[[파일:Visitor pattern class diagram in LePUS3.gif|frame|none|[[Lepus3|LePUS3]]의 비지터 ([https://web.archive.org/web/20180314162121/http://www.lepus.org.uk/ref/legend/legend.xml 범례])]]

== 예제 ==
=== C++ ===

<syntaxhighlight lang="cpp">
#include <iostream>
#include <string>
using namespace std;

// 1. Add an accept(Visitor) method to the "element" hierarchy
class Element
{
  public:
    virtual void accept(class Visitor &v) = 0;
};

class This: public Element
{
  public:
     /*virtual*/void accept(Visitor &v);
    string this()
    {
        return "This";
    }
};

class That: public Element
{
  public:
     /*virtual*/void accept(Visitor &v);
    string that()
    {
        return "That";
    }
};

class TheOther: public Element
{
  public:
     /*virtual*/void accept(Visitor &v);
    string theOther()
    {
        return "TheOther";
    }
};

// 2. Create a "visitor" base class w/ a visit() method for every "element" type
class Visitor
{
  public:
    virtual void visit(This *e) = 0;
    virtual void visit(That *e) = 0;
    virtual void visit(TheOther *e) = 0;
};

 /*virtual*/void This::accept(Visitor &v)
{
  v.visit(this);
}

 /*virtual*/void That::accept(Visitor &v)
{
  v.visit(this);
}

 /*virtual*/void TheOther::accept(Visitor &v)
{
  v.visit(this);
}

// 3. Create a "visitor" derived class for each "operation" to do on "elements"
class UpVisitor: public Visitor
{
     /*virtual*/void visit(This *e)
    {
        cout << "do Up on " + e->this() << '\n';
    }
     /*virtual*/void visit(That *e)
    {
        cout << "do Up on " + e->that() << '\n';
    }
     /*virtual*/void visit(TheOther *e)
    {
        cout << "do Up on " + e->theOther() << '\n';
    }
};

class DownVisitor: public Visitor
{
     /*virtual*/void visit(This *e)
    {
        cout << "do Down on " + e->this() << '\n';
    }
     /*virtual*/void visit(That *e)
    {
        cout << "do Down on " + e->that() << '\n';
    }
     /*virtual*/void visit(TheOther *e)
    {
        cout << "do Down on " + e->theOther() << '\n';
    }
};

int main()
{
  Element *list[] = 
  {
    new This(), new That(), new TheOther()
  };
  UpVisitor up; // 4. Client creates
  DownVisitor down; //    "visitor" objects
  for (int i = 0; i < 3; i++)
  //    and passes each
    list[i]->accept(up);
  //    to accept() calls
  for (i = 0; i < 3; i++)
    list[i]->accept(down);
}
// OUTPUT
//
// do Up on This
// do Up on That
// do Up on TheOther
// do Down on This
// do Down on That
// do Down on TheOther
</syntaxhighlight>

=== 자바 ===
<syntaxhighlight lang="java">
interface CarElementVisitor {
    void visit(Wheel wheel);
    void visit(Engine engine);
    void visit(Body body);
    void visit(Car car);
}

interface CarElement {
    void accept(CarElementVisitor visitor); // CarElements have to provide accept().
}

class Wheel implements CarElement {
    private String name;

    public Wheel(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}

class Engine implements CarElement {
    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}

class Body implements CarElement {
    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}

class Car implements CarElement{
    CarElement[] elements;

    public CarElement[] getElements() {
        return elements.clone(); // Return a copy of the array of references.
    }

    public Car() {
        this.elements = new CarElement[]
          { new Wheel("front left"), new Wheel("front right"),
            new Wheel("back left") , new Wheel("back right"),
            new Body(), new Engine() };
    }

    public void accept(CarElementVisitor visitor) {
        for(CarElement element : this.getElements()) {
            element.accept(visitor);
        }
        visitor.visit(this);
    }
}

class CarElementPrintVisitor implements CarElementVisitor {
    public void visit(Wheel wheel) {
        System.out.println("Visiting "+ wheel.getName()
                            + " wheel");
    }

    public void visit(Engine engine) {
        System.out.println("Visiting engine");
    }

    public void visit(Body body) {
        System.out.println("Visiting body");
    }

    public void visit(Car car) {
        System.out.println("Visiting car");
    }
}

class CarElementDoVisitor implements CarElementVisitor {
    public void visit(Wheel wheel) {
        System.out.println("Kicking my "+ wheel.getName() + " wheel");
    }

    public void visit(Engine engine) {
        System.out.println("Starting my engine");
    }

    public void visit(Body body) {
        System.out.println("Moving my body");
    }

    public void visit(Car car) {
        System.out.println("Starting my car");
    }
}

public class VisitorDemo {
    static public void main(String[] args){
        Car car = new Car();
        car.accept(new CarElementPrintVisitor());
        car.accept(new CarElementDoVisitor());
    }
}

</syntaxhighlight>

== 같이 보기 ==
* [[컴포지트 패턴]]

== 각주 ==
{{각주}}

{{디자인 패턴(소프트웨어)}}

[[분류:소프트웨어 디자인 패턴]]