디자인 패턴 ~Visitor~

1. 소개



GoF의 디자인 패턴에서 Visitor 패턴을 정리합니다.

2. Visitor 패턴이란?


  • Visitor라는 영어 단어는 방문자라는 의미입니다.
  • Visitor 패턴은 데이터 구조와 처리를 분리하는 방법입니다.
  • 데이터 구조를 둘러싼 방문자 클래스를 준비하고 방문자 클래스에 처리를 맡깁니다. 그러면 새로운 처리를 추가하고 싶을 때는 새로운 방문자를 만들어야 합니다. 그리고 데이터 구조는 방문자를 받아들이면 됩니다.
  • GoF 디자인 패턴은 동작에 대한 디자인 패턴으로 분류됩니다.

  • 3. 샘플 클래스 다이어그램





    4. 샘플 프로그램



    디렉토리, 파일 목록을 표시하는 프로그램입니다.

    4-1. Element 인터페이스



    Visitor 클래스의 인스턴스를 받아들이는 데이터 구조를 나타내는 인터페이스입니다.

    Element.java
    public interface Element {
        public abstract void accept(Visitor v);
    }
    

    4-2. Entry 클래스



    File나 Directory의 기본이 되는 클래스입니다. Element 인터페이스를 구현합니다.

    Entry.java
    public abstract class Entry implements Element {
    
        public abstract String getName();
    
        public String toString() {
            return getName();
        }
    }
    

    4-3. File 클래스



    파일을 나타내는 클래스입니다. 방문자의 수락 역할을합니다.

    File.java
    public class File extends Entry {
    
        private String name;
    
        public File(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void accept(Visitor v) {
            v.visit(this);
        }
    }
    

    4-4. Directory 클래스



    디렉토리를 나타내는 클래스입니다. 방문자의 수락 역할을합니다.

    Directory.java
    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class Directory extends Entry {
    
        private String name;
        private ArrayList<Entry> dir = new ArrayList<Entry>();
    
        public Directory(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public Entry add(Entry entry) {
            dir.add(entry);
            return this;
        }
    
        public Iterator<Entry> iterator() {
            return dir.iterator();
        }
    
        public void accept(Visitor v) {
            v.visit(this);
        }
    }
    

    4-5. Visitor 클래스



    파일이나 디렉토리를 방문하는 방문자를 나타내는 추상 클래스입니다.

    Visitor.java
    public abstract class Visitor {
        public abstract void visit(File file);
        public abstract void visit(Directory directory);
    }
    

    4-6. ListVisitor 클래스



    파일이나 디렉토리의 일람을 표시하는 클래스입니다.

    ListVisitor.java
    import java.util.Iterator;
    
    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;
        }
    }
    

    4-7. Main 클래스



    메인 처리를 실시하는 클래스입니다.

    Main.java
    public class Main {
        public static void main(String[] args) {
    
            Directory workspaceDir = new Directory("workspace");
            Directory compositeDir = new Directory("Visitor");
            Directory testDir1 = new Directory("test1");
            Directory testDir2 = new Directory("test2");
            workspaceDir.add(compositeDir);
            workspaceDir.add(testDir1);
            workspaceDir.add(testDir2);
    
            File element = new File("Element.java");
            File entity = new File("Entity.java");
            File file = new File("file.java");
            File directory = new File("Directory.java");
            File visitor = new File("Visitor.java");
            File listVisitor = new File("ListVisitor.java");
            File main = new File("main.java");
            compositeDir.add(element);
            compositeDir.add(entity);
            compositeDir.add(file);
            compositeDir.add(directory);
            compositeDir.add(visitor);
            compositeDir.add(listVisitor);
            compositeDir.add(main);
    
            workspaceDir.accept(new ListVisitor());
        }
    }
    

    4-8. 실행 결과


    /workspace
    /workspace/Visitor
    /workspace/Visitor/Element.java
    /workspace/Visitor/Entity.java
    /workspace/Visitor/file.java
    /workspace/Visitor/Directory.java
    /workspace/Visitor/Visitor.java
    /workspace/Visitor/ListVisitor.java
    /workspace/Visitor/main.java
    /workspace/test1
    /workspace/test2
    

    5. 장점



    Visitor 패턴은 처리를 복잡하게 하고 있는 것만으로, 「반복 처리가 필요하다면 데이터 구조안에 루프 처리를 쓰면 좋을까?」라고 느낍니다.
    Visitor 패턴의 목적은 데이터 구조와 처리를 분리하는 것입니다. 데이터 구조는 요소를 집합으로 정리하거나 요소간을 연결해 주는 것입니다. 그 구조를 유지해 두는 것과 그 구조를 기초로 한 처리를 쓰는 것은 다른 것입니다.
    방문자 역할(ListVisitor)은 수용 역할(File, Directory)과 독립적으로 개발할 수 있습니다. 즉, Visitor 패턴은 수용자(File, Directory) 클래스의 부품으로서의 독립성을 높이고 있습니다. 만약, 처리의 내용을 File 클래스나 Directory 클래스의 메소드로서 구현해 버리면, 새로운 처리를 추가해 기능 확장할 때마다 File 클래스나 Directory 클래스를 수정하지 않으면 안됩니다.

    6. GitHub


  • htps : // 기주 b. 코 m / 이타나카 730 /

  • 7. 디자인 패턴 목록


  • GoF 디자인 패턴 요약

  • 8. 참고



    이번 기사 및 샘플 프로그램은 이하의 서적을 바탕으로 작성하였습니다.
  • Java 언어로 배우는 디자인 패턴 입문

  • 매우 이해하기 쉽고 공부가되었습니다. 감사합니다.
    디자인 패턴이나 샘플 프로그램에 대한 설명이 상세하게 쓰여져 있으므로, 꼭 서적의 분도 봐 주세요.

    좋은 웹페이지 즐겨찾기