[DesignPattern] Visitor pattern

2014. 1. 11. 17:53Architecture/DesignPattern

반응형

Visitor Pattern


 개요

 예제(Java)

 같이보기

 참고 사항


<< 개요 >>

Visitor Pattern -  구조안을 돌아다니면서 일을 한다.


네이버 어학사전

(software, design, ) A behavioural design pattern that separats an algorithm from an object structure on which it operates. 


- 행위 디자인 패턴이고 객체 구조로부터 분리하는 하나의 방법이다. 이런 분리는 존재하고 있는 객체 구조에 그 구조를 수정하지 않고 새로운 동작을 추가 할 수 있도록 해준다. 이것은 open-closed principle에 따르는 하나의 방법이다.


또한, 오퍼레이션!! 동작이라고 생각하자.

비지터 패턴은 객체의 요소에 대해 수행하는 오퍼레이션을 나타낸다.

즉,  visitor(방문자)는 자신의 오퍼레이션의 대상이 되는 요소를 갖는 클래스를 수정하지 않고 새로운 오퍼레이션을 정의하는게 가능케한다.

적용영역으로 객체의 구조를 정의하는 클래스가 잘 변하지는 않으나, 구조 상에서 새로운 오펄이션을 정의 하고자 하는 경우나 하나의 객체에 대해서 관련이 적은, 상이한 오퍼레이션을 수행 할 필요가 있는 경우, 이러한 오퍼레이션에 의해 클래스가 난잡하게 되는 것을 막기 위해 사용한다.


요약하자면

1) 새로운 오퍼레이션 추가가 용이.

2) Visitor는 관련 있는 오퍼레이션을 묶고, 관련이 적은 오퍼레이션을 분리 시킨다.(OCP)

3) Visitor의 사용은 ConcreteElement Interface가 내부상태에 접근 할 수 있는 공개된 오퍼레이션 제공을 요구하며, 캡슐화(encapsulation)를 약화 시킨다.(단점?)


위의 말들이 맞는지는 아래를 보면서 확인 해보자.(사실 위의 말들이...처음에는 뭔소린가? 할 것이다ㅋㅋ)


[클래스 다이어그램]


<< 예제 Java >>

어떤 예제가 좋을까...고민하다가 비지터니깐 베지터로 해야겠다는 생각을 했다 ㅋㅋ

즉, Visitor == 베지터(Vesiter)가 된다. 캬캬; 

자! 그럼 재미있는 코딩을 해보자 ㅋㅋ      


결과부터 보면..

[ 결과 ]

베지터가 손오공과 함께 나메크성에 방문 하였습니다.

베지터가 프리저에게 대항하여 지구에서 전투 중입니다. 


[테스트 코드]

package kr.pe.acet.visitor;

import static org.junit.Assert.*;


import org.junit.Test;


public class VisitorTestCode {


@Test

public void visitorTest() {

Namek namekSung = new Namek("손오공");

namekSung.accept(new VisitPlanet());


Earth earth = new Earth("프리저");

earth.accept(new VisitPlanet());

}


}

 


자 이제 클래스 다이어그램을 보고 소스를 짜보자! 

우선 2개의 interface가 필요하다는 것을 알 수 가 있다.

Element, Visitor

1) Visitor(베지터) - 방문자

package kr.pe.acet.visitor;

public interface Vesiter {

public void visit(Namek namek);   // 나메크행성 방문

public void visit(Earth earth);        // 지구 방문

}



2) Element는 Accepter(수용자)의 역할을 한다.    즉, Vesiter의 동작이 방문할 곳을 나타내는 동작을 한다. 방문자(베지터)를 받아들이는 accept 메소드를 선언한다. accept 메소드의 인수로는 베지터의 오퍼레이션(동작)을 넘겨진다.


Accepter(수용자)

package kr.pe.acet.visitor;

public interface Accepter {

public void accept(Vesiter v);


}


3) 베지터 구현 소스 - VisitPlanet 

package kr.pe.acet.visitor;

public class VisitPlanet implements Vesiter{


@Override

public void visit(Namek namek) {

// TODO Auto-generated method stub

System.out.println("베지터가 "+namek.getName()+"과 함께 나메크성에 방문 하였습니다.");

}


@Override

public void visit(Earth earth) {

// TODO Auto-generated method stub

System.out.println("베지터가 "+earth.getName()+"에게 대항하여 지구에서 전투 중입니다.");

}


}



4) 수용자(Accepter) 구현 소스 - Namek 

package kr.pe.acet.visitor;

public class Namek implements Accepter{

String name;

public Namek(String name){

this.name= name;

}

public String getName() {

return name;

}


@Override

public void accept(Vesiter v) {

v.visit(this);

}


}

 


5) 수용자(Accepter) 구현 소스 - Earth 

package kr.pe.acet.visitor;

public class Earth implements Accepter{


private String name;

public Earth(String name) {

this.name=name;

}


public String getName() {

return name;

}


@Override

public void accept(Vesiter v) {

v.visit(this);

}


}

 


위에서 구조를 하나 더 넣어보면..!!


<< 같이 보기 >>

스터디 - 2014.01.13

  라낑님 : 구조에서 분리 시키는 방법. 행위에 관련 된 것을 인터페이스로 뽑아 냄. 

              위키피디아 소스로 진행.

              구조에 대한 정의는 미리 Visitor 인터페이스로 정의(Wheel, Engine, Body 등등)

  굿택님 : 객체구조를 비지터가 방문하여 뭔가를 빼낸다고 이해 함.

              내가 짠 소스를 비유하면 나메크성과 지구가 객체구조이고, 베지터가 방문을 한다고 보면 된다.

             Acceptor가 받아줘야 함. 받아줬을 때만 방문을 허락 함. ppt 파일 소개, 예제 확인(야동관련).


<< 참고 사항 >>

다시 보도록 하자. 사실 위에서 말했던 "구조를 수정하지 않고 새로운 동작을 추가 할 수 있도록 해준다"에서 구조라는 것이 헷깔렸었다..스터디를 통해서 정확히 알 수 있었다.

여기에서 구조라는 것은 Visitor의 구조 이다. 즉, 베지터의 구조 이다.

베지터의 구조!!

        public void visit(Namek namek);   // 나메크행성 방문

public void visit(Earth earth);


이 구조를 가지고 새로운 동작을 추가!! 즉, VisitPlanet 와 같은 동작을 쉽게! 추가 할 수 가 있다. 

AttackPlanet을 하나 추가 해보자!


- Attackplanet.java

package kr.pe.acet.visitor;

public class AttackPlanet implements Vesiter{


@Override

public void visit(Namek namek) {

// TODO Auto-generated method stub

System.out.println("베지터가 "+namek.getName()+"과 함께 나메크성에 공격 하였습니다.");

}


@Override

public void visit(Earth earth) {

// TODO Auto-generated method stub

System.out.println("베지터가 "+earth.getName()+"에게 대항하여 지구에서 전투 중입니다.");

}


}

 




행위 디자인 패턴이고 객체 구조로부터 분리하는 하나의 방법이다. 이런 분리는 존재하고 있는 객체 구조에 그 구조를 수정하지 않고 새로운 동작을 추가 할 수 있도록 해준다. 이것은 open-closed principle에 따르는 하나의 방법이다.


필자는..구조가 너무 헷깔려서...Moon이라는 Class를 추가하여 새로운 동작을 추가 하고자 했었다..


자신의 오퍼레이션의 대상이 되는 요소를 갖는 클래스를 수정하지 않고 새로운 오퍼레이션을 정의하는게 가능케한다."

에서도 마찬가지이다. 클래스를 수정하지 않는다에서의 클래스는 Visitor 이며, 새로운 오퍼레이션이라는 것은 VisitPlanet같은 Visitor의 구현체인 것이다.



- END -

    

반응형