이번 학습 주제는
방문자 패턴(Visitor Patter)입니다
방문자 패턴은
방문자를 나타내는 클래스를 준비하고
이 클래스에게 처리를 위임함으로써
데이터 구조와 처리를 분리합니다
먼저 방문자 패턴의 역할들을
정리하고 시작하겠습니다
역할 | 설명 |
Visitor(방문자) | 데이터 구조의 전체적인 요소마다 visit 메소드 선언 |
Concrete Visitor(구체적인 방문자) | Visitor 역할의 인터페이스를 구현 |
Element(요소) | Visitor 역할이 방문할 곳을 나타내는 역할로 방문자를 받아들이는 accept 메소드 선언 |
Concrete Element(구체적인 요소) | Element 역할의 인터페이스를 구현 |
Object Structure(오브젝트 구조) | Element 역할의 집합을 취급하는 역할 |
이제 구현을 하겠습니다
지난 디자인 패턴 학습 중에
Composite Pattern 내용을
조금 수정하는 것으로 될 것 같네요
Composite Pattern이 궁금하시다면
아래의 링크 ↓↓
2020/07/05 - [Java] - [Design Pattern] 복합체 패턴(Composite Pattern)
1. 추상 클래스(Abstract Class) Visitor.java
package visitorPattern;
public abstract class Visitor {
public abstract void visit(File file);
public abstract void visit(Directory directory);
}
2. 클래스(Class) ListVisitor.java
package visitorPattern;
import java.util.*;
public class ListVisitor extends Visitor {
private String currentDir = "";
public void visit(File file) {
System.out.println(currentDir + "/" + file);
}
public void visit(Directory directory) {
System.out.println(currentDir + "/" + directory);
String saveDir = currentDir;
currentDir = currentDir + "/" + directory.getName();
Iterator<Entry> it = directory.iterator();
while ( it.hasNext() ) {
Entry entry = (Entry) it.next();
entry.accept(this);
}
currentDir = saveDir;
}
}
3. 인터페이스(Interface) Element.java
package visitorPattern;
public interface Element {
public abstract void accept(Visitor v);
}
4. 추상 클래스(Abstract Class) Entry.java
package visitorPattern;
import java.util.Iterator;
public abstract class Entry implements Element {
public abstract String getName();
public abstract int getSize();
public Entry add(Entry entry) throws FileTreatmentException {
throw new FileTreatmentException();
}
public Iterator<Entry> iterator() throws FileTreatmentException {
throw new FileTreatmentException();
}
public String toString() {
return getName() + " (" + getSize() + ")";
}
}
5. 클래스(Class) Directory.java
package visitorPattern;
import java.util.*;
public class Directory extends Entry {
private String name;
private ArrayList<Entry> directory = new ArrayList<Entry>();
public Directory(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getSize() {
int size = 0;
Iterator<Entry> it = directory.iterator();
while ( it.hasNext() ) {
Entry entry = (Entry) it.next();
size += entry.getSize();
}
return size;
}
public Entry add(Entry entry) {
directory.add(entry);
return this;
}
public Iterator<Entry> iterator() {
return directory.iterator();
}
public void accept(Visitor v) {
v.visit(this);
}
}
6. 클래스(Class) File.java
package visitorPattern;
public class File extends Entry {
private String name;
private int size;
public File(String name, int size) {
this.name = name;
this.size = size;
}
public String getName() {
return name;
}
public int getSize() {
return size;
}
public void accept(Visitor v) {
v.visit(this);
}
}
7. 클래스(Class) FileTreatmentException.java
package visitorPattern;
public class FileTreatmentException extends RuntimeException {
public FileTreatmentException() {
}
public FileTreatmentException(String msg) {
super(msg);
}
}
8. 클래스(Class) Test.java
import visitorPattern.*;
public class Test {
public static void main(String[] args) {
/* Visitor Pattern */
try {
System.out.println("Making root entries...");
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("vi", 10000));
binDir.add(new File("latex", 20000));
rootDir.accept(new ListVisitor());
System.out.println("");
System.out.println("Making user entries...");
Directory Kim = new Directory("Kim");
Directory Lee = new Directory("Lee");
Directory Park = new Directory("Park");
Directory Sa = new Directory("Sa");
usrDir.add(Kim);
usrDir.add(Lee);
usrDir.add(Park);
usrDir.add(Sa);
Kim.add(new File("diary.html", 100));
Lee.add(new File("memo.txt", 200));
Park.add(new File("game.c", 300));
Sa.add(new File("Composite.java", 400));
rootDir.accept(new ListVisitor());
} catch ( FileTreatmentException e ) {
e.printStackTrace();
}
}
}
위의 코드를 보시면
Visitor 패턴에서는
Concrete Element, Concrete Visitor
한쌍에 의해 실제 처리가 결정됩니다
이런 것을 더블 디스패치(Double Dispatch)라고 합니다
그런데 너무 복잡해보이네요-_-
앞에서도 언급했지만
Visitor 패턴의 주요 목적이
처리를 데이터 구조로부터 분리하는 것인데
이렇게 함으로써 목적을 달성합니다
참고 ☞ The Open-Closed Principle(OCP) 원칙
이번 주제는 이해하기 다소 어려웠는데
Concrete Visitor를 추가하거나
Concrete Element를 추가해보면서
좀 더 학습해봐야겠습니다
아무튼 오늘의 학습은
이것으로 마치겠습니다
그럼 이만-_-
'Java' 카테고리의 다른 글
[Design Pattern] 창구 패턴(Facade Pattern)과 중개자 패턴(Mediator Pattern) (0) | 2020.07.13 |
---|---|
[Design Pattern] 책임 떠넘기기 패턴(Chain of Responsibility Pattern) (0) | 2020.07.12 |
[Design Pattern] 데코레이터 패턴(Decorator Pattern) (0) | 2020.07.07 |
[Design Pattern] 복합체 패턴(Composite Pattern) (0) | 2020.07.05 |
[Design Pattern] 전략 패턴(Strategy Pattern) (0) | 2020.06.29 |