さぁ、ラストの Visitor パターン(一覧)。
Visitor パターンの登場人物
- @Visitor → 型
- elementType : Class<?>
- @Visit → メソッド
- @ConcreteVisitor → 具象クラス
- visitorType : Class<?>
- @Element → 型
- visitorType : Class<?>
- @Accept → メソッド
- @ConcreteElement → 具象クラス
- elementType : Class<?>
- @ObjectStructure → 型
- elementType : Class<?>
アノテーション定義
上記の定義の具体的な Java コード。
package org.waman.tools.design.gof.behavioral; import java.lang.annotation.*; public final class VisitorPattern { private VisitorPattern(){} @Target(ElementType.TYPE) public static @interface Element{ Class<?> visitorType() default Void.class; @Inherited @Target(ElementType.METHOD) public static @interface Accept{} } @Target(ElementType.TYPE) public static @interface ConcreteElement{ Class<?> elementType() default Void.class; } @Target(ElementType.TYPE) public static @interface ObjectStructure{ Class<?> elementType() default Void.class; } @Target(ElementType.TYPE) public static @interface Visitor{ Class<?> elementType() default Void.class; @Inherited @Target(ElementType.METHOD) public static @interface Visit{} } @Target(ElementType.TYPE) public static @interface ConcreteVisitor{ Class<?> visitorType() default Void.class; } }
サンプルコード in 『Java 言語で学ぶデザインパターン入門』
Element.java
@Element 役のインターフェース。
import org.waman.tools.design.gof.behavioral.VisitorPattern; import org.waman.tools.design.gof.behavioral.VisitorPattern.Element.Accept; @VisitorPattern.Element(visitorType = Visitor.class) public interface Element { @Accept public abstract void accept(Visitor v); }
Entry.java, File.java, Directory.java
import java.util.Iterator; public abstract class Entry implements Element { ... }
import org.waman.tools.design.gof.behavioral.VisitorPattern; @VisitorPattern.ConcreteElement(elementType = Element.class) public class File extends Entry { ... @Override public void accept(Visitor v) { v.visit(this); } }
import java.util.*; import org.waman.tools.design.gof.behavioral.VisitorPattern; @VisitorPattern.ConcreteElement(elementType = Element.class) @VisitorPattern.ObjectStructure(elementType = Element.class) public class Directory extends Entry implements Iterable<Entry> { ... @Override public Iterator<Entry> iterator() {...} @Override public void accept(Visitor v) { v.visit(this); } }
Directory クラスは @Element 役と @ObjectStructure 役の二役。
Visitor.java
@Visitor 役のクラス。
import org.waman.tools.design.gof.behavioral.VisitorPattern; import org.waman.tools.design.gof.behavioral.VisitorPattern.Visitor.Visit; @VisitorPattern.Visitor(elementType = Entry.class) public abstract class Visitor { @Visit public abstract void visit(File file); @Visit public abstract void visit(Directory directory); }
ListVisitor.java
@ConcreteVisitor 役のクラス。
@VisitorPattern.ConcreteVisitor(visitorType = Visitor.class) public class ListVisitor extends Visitor { private String currentdir = ""; @Override public void visit(File file) { System.out.println(currentdir + "/" + file); } @Override public void visit(Directory directory) { System.out.println(currentdir + "/" + directory); String savedir = currentdir; currentdir = currentdir + "/" + directory.getName(); for(Entry entry: directory) entry.accept(this); currentdir = savedir; } }