visitor pattern

25
Visitor Pattern http://www.k.hosei.ac.jp/ ~yukita/

Upload: tana-weeks

Post on 01-Jan-2016

27 views

Category:

Documents


0 download

DESCRIPTION

Visitor Pattern. http://www.k.hosei.ac.jp/~yukita/. Visitor Pattern の目的. データ構造と処理の分離. 例題のクラス図. Uses. Uses. Uses. Visitor.java. public abstract class Visitor { public abstract void visit(File file); public abstract void visit(Directory directory); }. Acceptor.java. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Visitor Pattern

Visitor Pattern

http://www.k.hosei.ac.jp/~yukita/

Page 2: Visitor Pattern

Visitor Pattern 2

Visitor Pattern の目的

• データ構造と処理の分離

Page 3: Visitor Pattern

Visitor Pattern 3

例題のクラス図

Visitor

visit(File)

visit(Directory)

<<interface>>

Acceptor

accept

ListVisitor

currentdir

visit(File)

visit(Directory)

Entry

getName

getSize

add

iterator

Directory

name

dir

accept

getName

getSize

add

iterator

File

name

size

accept

getName

getSize

Main

Uses

Uses

Uses

Page 4: Visitor Pattern

Visitor Pattern 4

Visitor.java

public abstract class Visitor {

public abstract void visit(File file);

public abstract void visit(Directory directory);

}

Page 5: Visitor Pattern

Visitor Pattern 5

Acceptor.java

public interface Acceptor {

public abstract void accept(Visitor v);

}

Page 6: Visitor Pattern

Visitor Pattern 6

Entry.java (1)

import java.util.Iterator;

public abstract class Entry implements Acceptor {

public abstract String getName();

public abstract int getSize();

public Entry add(Entry entry)

throws FileTreatmentException {

throw new FileTreatmentException();

}

Page 7: Visitor Pattern

Visitor Pattern 7

Entry.java (2) public Iterator iterator()

throws FileTreatmentException {

throw new FileTreatmentException();

}

public String toString() {

return getName() + " (" + getSize() + ")";

}

}

Page 8: Visitor Pattern

Visitor Pattern 8

Entry におけるダミー実装

• add, iterator メソッドは File ではエラーとなる。

• add, iterator メソッドは Directory で意味をもつ。

Page 9: Visitor Pattern

Visitor Pattern 9

File.java (1)

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;

}

Page 10: Visitor Pattern

Visitor Pattern 10

File.java (2)

public int getSize() {

return size;

}

public void accept(Visitor v) {

v.visit(this);

}

}

Page 11: Visitor Pattern

Visitor Pattern 11

Directory.java (1)import java.util.Iterator;

import java.util.Vector;

public class Directory extends Entry {

private String name;

private Vector dir = new Vector();

public Directory(String name) {

this.name = name;

}

public String getName() {

return name;

}

Page 12: Visitor Pattern

Visitor Pattern 12

Directory.java (2) public int getSize() {

int size = 0;

Iterator it = dir.iterator();

while (it.hasNext()) {

Entry entry = (Entry)it.next();

size += entry.getSize();

}

return size;

}

public Entry add(Entry entry) {

dir.add(entry);

return this;

}

Page 13: Visitor Pattern

Visitor Pattern 13

Directory.java (3) public Iterator iterator() {

return dir.iterator();

}

public void accept(Visitor v) {

v.visit(this);

}

}

Page 14: Visitor Pattern

Visitor Pattern 14

ListVisitor.java (1)

import java.util.Iterator;

public class ListVisitor extends Visitor {

private String currentdir = "";

public void visit(File file) {

System.out.println(currentdir + "/" + file);

}

Page 15: Visitor Pattern

Visitor Pattern 15

ListVisitor.java (2) public void visit(Directory directory) {

System.out.println(currentdir + "/" + directory);

String savedir = currentdir;

currentdir = currentdir + "/" + directory.getName();

Iterator it = directory.iterator();

while (it.hasNext()) {

Entry entry = (Entry)it.next();

entry.accept(this);

}

currentdir = savedir;

}

}

Page 16: Visitor Pattern

Visitor Pattern 16

Visitor が処理を担当

• Visitor インタフェースを実装しているListVisitor が処理を担当する。

• 一方, Acceptor 側の File, Directory は処理を担わず,データの保持だけに責任をもつ。

Page 17: Visitor Pattern

Visitor Pattern 17

FileTreatmentException.java

public class FileTreatmentException

extends RuntimeException {

public FileTreatmentException() {

}

public FileTreatmentException(String msg) {

super(msg);

}

}

Page 18: Visitor Pattern

Visitor Pattern 18

Main.java (1)public class Main {

public static void main(String[] args) {

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");

Page 19: Visitor Pattern

Visitor Pattern 19

Main.java (2) 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...");

Page 20: Visitor Pattern

Visitor Pattern 20

Main.java (3) Directory yuki = new Directory("yuki");

Directory hanako = new Directory("hanako");

Directory tomura = new Directory("tomura");

usrdir.add(yuki);

usrdir.add(hanako);

usrdir.add(tomura);

yuki.add(new File("diary.html", 100));

yuki.add(new File("Composite.java", 200));

Page 21: Visitor Pattern

Visitor Pattern 21

Main.java (4) hanako.add(new File("memo.tex", 300));

tomura.add(new File("game.doc", 400));

tomura.add(new File("junk.mail", 500));

rootdir.accept(new ListVisitor());

} catch (FileTreatmentException e) {

e.printStackTrace();

}

}

}

Page 22: Visitor Pattern

Visitor Pattern 22

実行結果Making root entries.../root (30000)/root/bin (30000)/root/bin/vi (10000)/root/bin/latex (20000)/root/tmp (0)/root/usr (0)

Making user entries.../root (31500)/root/bin (30000)/root/bin/vi (10000)/root/bin/latex (20000)/root/tmp (0)/root/usr (1500)/root/usr/yuki (300)/root/usr/yuki/diary.html (100)/root/usr/yuki/Composite.java (200)/root/usr/hanako (300)/root/usr/hanako/memo.tex (300)/root/usr/tomura (900)/root/usr/tomura/game.doc (400)/root/usr/tomura/junk.mail (500)

Page 23: Visitor Pattern

Visitor Pattern 23

Sequence DiagramMain :Directory :File :File

:ListVisitornewaccept

visitaccept

visit

visitaccept

Page 24: Visitor Pattern

Visitor Pattern 24

パターン

Visitor

visit(ConcreteAcceptorA)

visit(ConcreteAcceptorB)

Acceptor

accept

ConcreteAcceptorA

accept

ConcreteVisitor

visit(ConcreteAcceptorA)

visit(ConcreteAcceptorB)

ConcreteAcceptorB

accept

ObjectStructure

Page 25: Visitor Pattern

Visitor Pattern 25

注意

• ConcreteVisitor の追加は簡単– このとき ConcreteAcceptor の変更は不要

• ConcreteAcceptor の使いは困難– 例えば Entry のサブクラス Device を追

加しようとすれば Visit(Device) メソッドが Visitor 側に必要になる。