2016년 1월 8일 금요일

Visitor Pattern (방문자 패턴)

의도
  • 객체 구조를 이루는 원소에 대해 수행할 연산을 표현하는 패턴
이럴 때 사용하자.
  • 객체 구조가 다른 인터페이스를 가진 클래스들을 포함하고 있어서 구체적 클래스에 따라 이들 오퍼레이션을 수행하고자 할 때
  • 구별되고 관련되지 않은 많은 오퍼레이션이 객체에 수핼될 필요가 있지만, 오퍼레이션으로 인해 클래스들을 복잡하게 하고 싶지 않을 때
장점은?
  • 새로운 연산을 쉽게 추가 가능
  • 연산자들을 한 군데로 모으고 관련되지 않은 연산을 떼어낼 수 있음
단점은?
  • 데이터 은닉을 깰 수 있음
코드
Element, Visitor 클래스
class Element
{
public:
   virtual void accept(class Visitor& rVisitor) = 0;
};

class Visitor
{
public:
   virtual void visit(class This* pElement) = 0;
   virtual void visit(class That* pElement) = 0;
   virtual void visit(class TheOther* pElement) = 0;
};

This, That, TheOther 클래스
class This : public Element
{
public:
   void accept(Visitor& rVisitor) {
      rVisitor.visit(this);
   };
   string thiss() {
      return "This";
   };
};

class That : public Element
{
public:
   void accept(Visitor& rVisitor) {
      rVisitor.visit(this);
   };
   string that() {
      return "That";
   };
};

class TheOther : public Element
{
public:
   void accept(Visitor& rVisitor) {
      rVisitor.visit(this);
   };
   string theOther() {
      return "TheOther";
   };
};

UpVisitor, DownVisitor 클래스
class UpVisitor : public Visitor
{
   void visit(This* pElement) {
      cout << "do Up on" + pElement->thiss() << endl;
   };
   void visit(That* pElement) {
      cout << "do Up on" + pElement->that() << endl;
   };
   void visit(TheOther* pElement) {
      cout << "do Up on" + pElement->theOther() << endl;
   };
};

class DownVisitor : public Visitor
{
   void visit(This* pElement) {
      cout << "do Down on" + pElement->thiss() << endl;
   };
   void visit(That* pElement) {
      cout << "do Down on" + pElement->that() << endl;
   };
   void visit(TheOther* pElement) {
      cout << "do Down on" + pElement->theOther() << endl;
   };
};

실행부분
void main()
{
   Element* pArrayElement[] = { new This(), new That(), new TheOther() };
   UpVisitor upVisitor;
   DownVisitor downVisitor;

   for each (Element* pElement in pArrayElement) {
      pElement->accept(upVisitor);
   }
   for each (Element* pElement in pArrayElement) {
      pElement->accept(downVisitor);
   }

   for each (Element* pElement in pArrayElement) {
      delete pElement;
   }
}

UML - class 다이어그램
참고
  • GoF의 디자인 패턴(개정판) 재사용성을 지닌 객체지향 소프트웨어의 핵심요소
  • http://pusna25.blog.me/100197705146
  • https://ko.wikipedia.org/wiki/%EB%B9%84%EC%A7%80%ED%84%B0_%ED%8C%A8%ED%84%B4

댓글 없음:

댓글 쓰기

참고: 블로그의 회원만 댓글을 작성할 수 있습니다.