Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
design_pattern:visitor_pattern [2017/10/31 03:03] ledyxdesign_pattern:visitor_pattern [2021/02/07 03:30] (current) – [Visitor Pattern] ledyx
Line 1: Line 1:
 = Visitor Pattern = = Visitor Pattern =
-객체 구조를 돌아다니면서 동일한 조작을 반복해서 적용하기. 이 때, '객체 구조'와 '처리(Algorithm)'을 분리하는 것이 핵심.+객체 구조를 돌아다니면서 동일한 조작을 반복해서 적용하기. 이 때, '객체 구조'와 '처리(Algorithm)'을 분리하는 것이 핵심. 개방-폐쇄 원칙(OCP, Open-Closed Principle)[(기존 클래스를 수정하지 않고 확장할 수 있도록 하는 것. https://ko.wikipedia.org/wiki/%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84_%EC%9B%90%EC%B9%99)]을 적용한 방법중 하나.
  
   * 언제 사용하는가?   * 언제 사용하는가?
-    * 데이터 구조 안에 많은 요소가 저장되어 있고, 그 각 요소에 대해서 __다른 종류__의 __<fc red>처리(Algorithm)</fc>__가 필요한 경우+    * 데이터 구조 안에 많은 요소가 저장되어 있고, 그 각 요소에 대해서 __다른 종류의 <fc red>처리(Algorithm)</fc>__가 필요한 경우 
 +    * 이로써 얻는 이점으로 객체 구조와 처리 역할을 독립적으로 확장 가능!
  
  
-{{tag>Architecture Modeling DesignPattern Behavioral}}+{{tag>Architecture Modeling Design_Pattern Behavioral}}
  
 +시나리오
 +  * [[composite pattern]]의 예제인 "파일 시스템"을 객체 구조(Element, ObjectStructure)로 이용. 여기서 처리 알고리즘을 분리시킨다.
 +
 +
 += Visitor =
 +Method Overloading을 이용하여 각각의 처리할 Logic 수행하는 역할.
 +
 +<sxh java ; title:Visitor ; highlight:[7-8]>
 +package visitor;
 +
 +import element.objectstructure.concrete.Directory;
 +import element.objectstructure.concrete.File;
 +
 +public abstract class Visitor {
 + public abstract void visit(File file);
 + public abstract void visit(Directory directory);
 +}
 +</sxh>
 +
 +<sxh java ; title:ConcreteVisitor ; highlight:[28]>
 +package visitor.concrete;
 +
 +import java.util.Iterator;
 +
 +import element.objectstructure.Entry;
 +import element.objectstructure.concrete.Directory;
 +import element.objectstructure.concrete.File;
 +import visitor.Visitor;
 +
 +public class ListVisitor extends Visitor {
 +
 + private String currentDirectoryName = "";
 +
 + @Override
 + public void visit(File file) {
 + System.out.println(currentDirectoryName + " / " + file);
 + }
 +
 + @Override
 + public void visit(Directory directory) {
 + System.out.println(currentDirectoryName + " / " + directory);
 +
 + String tempDirectoryName = currentDirectoryName;
 +
 + currentDirectoryName = new StringBuilder(currentDirectoryName).append("/").append(directory.getName()).toString();
 + Iterator<Entry> it = directory.iterator();
 + while(it.hasNext()) {
 + it.next().accept(this);
 + }
 +
 + currentDirectoryName = tempDirectoryName; 
 + }
 +}
 +</sxh>
 +
 +
 += Element =
 +방문할 객체를 지정하는 역할. accept()로 요청하여 객체 각각의 처리 Logic 수행.
 +
 +<sxh java ; title:Element>
 +package element;
 +
 +import visitor.Visitor;
 +
 +public interface Element {
 + void accept(Visitor visitor);
 +}
 +</sxh>
 +
 +<sxh java ; title:(Component)>
 +package element.objectstructure;
 +
 +import java.util.Iterator;
 +
 +import element.Element;
 +import element.objectstructure.exception.FileTreatmentException;
 +
 +public abstract class Entry implements Element {
 + public abstract String getName();
 + public abstract int getSize();
 +
 + /* Directory에서만 유효 */
 + public Entry add(Entry entry) throws FileTreatmentException {
 + throw new FileTreatmentException();
 + }
 +
 + /* 객체 구조의 각 요소에 특정한 처리를 실행하는 데 필요 */
 + /* Directory에서만 유효 */
 + public Iterator<Entry> iterator() throws FileTreatmentException {
 + throw new FileTreatmentException();
 + }
 +
 + @Override
 + public String toString() {
 + StringBuilder sb = new StringBuilder();
 + sb.append(getName());
 + sb.append(" (");
 + sb.append(getSize());
 + sb.append(") ");
 +
 + return sb.toString();
 + }
 +}
 +</sxh>
 +
 +<sxh java ; title:ConcreteElement (Leaf)>
 +package element.objectstructure.concrete;
 +
 +import element.objectstructure.Entry;
 +import visitor.Visitor;
 +
 +public class File extends Entry {
 +
 + private String name;
 + private int size;
 +
 + public File(String name, int size) {
 + this.name = name;
 + this.size = size;
 + }
 +
 + @Override
 + public void accept(Visitor visitor) {
 + visitor.visit(this);
 + }
 +
 + @Override
 + public String getName() {
 + return name;
 + }
 +
 + @Override
 + public int getSize() {
 + return size;
 + }
 +
 +}
 +</sxh>
 +
 +<sxh java ; title:ObjectStructure, ConcreteElement (Composite)>
 +package element.objectstructure.concrete;
 +
 +import java.util.ArrayList;
 +import java.util.Iterator;
 +
 +import element.objectstructure.Entry;
 +import element.objectstructure.exception.FileTreatmentException;
 +import visitor.Visitor;
 +
 +public class Directory extends Entry {
 +
 + private String name;
 + private ArrayList<Entry> directories = new ArrayList<>();
 +
 + public Directory(String name) {
 + this.name = name;
 + }
 +
 + @Override
 + public void accept(Visitor visitor) {
 + visitor.visit(this);
 + }
 +
 + @Override
 + public String getName() {
 + return name;
 + }
 +
 + @Override
 + public int getSize() {
 + return directories.size();
 + }
 +
 + @Override
 + public Entry add(Entry entry) throws FileTreatmentException {
 + directories.add(entry);
 + return this;
 + }
 +
 + @Override
 + public Iterator<Entry> iterator() throws FileTreatmentException {
 + return directories.iterator();
 + }
 +}
 +</sxh>
 +
 +<sxh java ; collapse:true>
 +package element.objectstructure.exception;
 +
 +public class FileTreatmentException extends RuntimeException {
 + public FileTreatmentException() {
 + }
 +
 + public FileTreatmentException(String message) {
 + super(message);
 + }
 +}
 +</sxh>
 +
 += Client =
 +<sxh java ; highlight:[18]>
 +import element.objectstructure.concrete.Directory;
 +import element.objectstructure.concrete.File;
 +import visitor.concrete.ListVisitor;
 +
 +public class Client {
 +    public static void main(String[] args) {
 +    Directory rootdir = new Directory("root");
 +        Directory bindir = new Directory("bin");
 +        Directory tmpdir = new Directory("tmp");
 +        Directory usrdir = new Directory("usr");
 +        rootdir.add(bindir);
 +        rootdir.add(tmpdir);
 +        rootdir.add(usrdir);
 +         
 +        bindir.add(new File("sub1", 10000));
 +        bindir.add(new File("sub2", 20000));
 +        
 +        rootdir.accept(new ListVisitor());
 +    }
 +}
 +
 +/*
 + / root (3) 
 +/root / bin (2) 
 +/root/bin / vi (10000) 
 +/root/bin / latex (20000) 
 +/root / tmp (0) 
 +/root / usr (0) 
 +*/
 +</sxh>
design_pattern/visitor_pattern.1509419012.txt.gz · Last modified: 2021/02/07 03:15 (external edit)