This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| design_pattern:visitor_pattern [2017/10/30 16:45] – ledyx | design_pattern:visitor_pattern [2021/02/07 03:30] (current) – [Visitor Pattern] ledyx | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| = Visitor Pattern = | = Visitor Pattern = | ||
| - | 데이터 | + | 객체 |
| * 언제 사용하는가? | * 언제 사용하는가? | ||
| - | * 데이터 구조 안에 많은 요소가 저장되어 있고, 그 각 요소에 대해서 __여러 | + | * 데이터 구조 안에 많은 요소가 저장되어 있고, 그 각 요소에 대해서 __다른 |
| + | * 이로써 얻는 이점으로 객체 구조와 처리 역할을 독립적으로 확장 가능! | ||
| - | {{tag> | + | {{tag> |
| + | 시나리오 | ||
| + | * [[composite pattern]]의 예제인 " | ||
| + | |||
| + | |||
| + | = Visitor = | ||
| + | Method Overloading을 이용하여 각각의 처리할 Logic 수행하는 역할. | ||
| + | |||
| + | <sxh java ; title: | ||
| + | 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 java ; title: | ||
| + | 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("/" | ||
| + | Iterator< | ||
| + | while(it.hasNext()) { | ||
| + | it.next().accept(this); | ||
| + | } | ||
| + | |||
| + | currentDirectoryName = tempDirectoryName; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | = Element = | ||
| + | 방문할 객체를 지정하는 역할. accept()로 요청하여 객체 각각의 처리 Logic 수행. | ||
| + | |||
| + | <sxh java ; title: | ||
| + | package element; | ||
| + | |||
| + | import visitor.Visitor; | ||
| + | |||
| + | public interface Element { | ||
| + | void accept(Visitor visitor); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <sxh java ; title: | ||
| + | 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< | ||
| + | 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 java ; title: | ||
| + | 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 java ; title: | ||
| + | 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< | ||
| + | |||
| + | 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< | ||
| + | return directories.iterator(); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <sxh java ; collapse: | ||
| + | package element.objectstructure.exception; | ||
| + | |||
| + | public class FileTreatmentException extends RuntimeException { | ||
| + | public FileTreatmentException() { | ||
| + | } | ||
| + | |||
| + | public FileTreatmentException(String message) { | ||
| + | super(message); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | = Client = | ||
| + | <sxh java ; highlight: | ||
| + | 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(" | ||
| + | Directory bindir = new Directory(" | ||
| + | Directory tmpdir = new Directory(" | ||
| + | Directory usrdir = new Directory(" | ||
| + | rootdir.add(bindir); | ||
| + | rootdir.add(tmpdir); | ||
| + | rootdir.add(usrdir); | ||
| + | |||
| + | bindir.add(new File(" | ||
| + | bindir.add(new File(" | ||
| + | | ||
| + | rootdir.accept(new ListVisitor()); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | /* | ||
| + | / root (3) | ||
| + | /root / bin (2) | ||
| + | /root/bin / vi (10000) | ||
| + | /root/bin / latex (20000) | ||
| + | /root / tmp (0) | ||
| + | /root / usr (0) | ||
| + | */ | ||
| + | </ | ||