Javaã«ãããã¶ã¤ã³ãã¿ã¼ã³ã®7åç®ã§ãï¼
ä»åãææã¯ãåèæç®ã®ãJavaè¨èªã§å¦ã¶ãã¶ã¤ã³ãã¿ã¼ã³å
¥é第3çãã®ãµã³ãã«ã³ã¼ãã使ããã¦é ãã¾ãã
ä»åã¯ãVisitorãã¿ã¼ã³ã§ããä»åãã¤ã¡ã¼ã¸ãããããã¿ã¼ã³ã§ããã
ã§ã¯ããã£ã¦ããã¾ãããï¼
åèæç®
åèæç®ã®ãµã³ãã«ããã°ã©ã ã®ãã¦ã³ãã¼ã
www.hyuki.com
ã¯ããã«
ãJavaã§ãã¶ã¤ã³ãã¿ã¼ã³ãå¦ã¶ãã®è¨äºä¸è¦§ã§ããè¯ãã£ããåèã«ãã¦ãã ããã
Javaã§ãã¶ã¤ã³ãã¿ã¼ã³ã®è¨äºä¸è¦§
å
ã«ã23種é¡ã®ãã¶ã¤ã³ãã¿ã¼ã³ã示ãã¾ãã
åèãµã¤ãï¼デザインパターン (ソフトウェア) - Wikipedia
ãã¶ã¤ã³ãã¿ã¼ã³ä¸è¦§
âçæã«é¢ãããã¿ã¼ã³
ãã»Abstract Factoryï¼é¢é£ããã¤ã³ã¹ã¿ã³ã¹ãç¶æ³ã«å¿ãã¦ãé©åã«çæããæ¹æ³ãæä¾ãã
ãã»Builderï¼è¤ååãããã¤ã³ã¹ã¿ã³ã¹ã®çæéç¨ãé è½ããã
ãã»Factory Methodï¼çæãããã¤ã³ã¹ã¿ã³ã¹ã«ä¾åããªããã¤ã³ã¹ã¿ã³ã¹ã®çææ¹æ³ãæä¾ãã
ãã»Prototypeï¼åæ§ã®ã¤ã³ã¹ã¿ã³ã¹ãçæããããã«ãååã®ã¤ã³ã¹ã¿ã³ã¹ãè¤è£½ãã
ãã»Singletonï¼ããã¯ã©ã¹ã«ã¤ãã¦ãã¤ã³ã¹ã¿ã³ã¹ã1ã¤ããåå¨ããªããã¨ãä¿è¨¼ãã
âæ§é ã«é¢ãããã¿ã¼ã³
ãã»Adapterï¼å
ã
é¢é£æ§ã®ãªã2ã¤ã®ã¯ã©ã¹ãæ¥ç¶ããã¯ã©ã¹ãä½ã
ãã»Bridgeï¼ã¯ã©ã¹ã¨å¼ã³åºãå´ã®éã®æ©æ¸¡ããããã¯ã©ã¹ã§ãå®è£
ãé è½ãã
ãã»Compositeï¼å帰çãªæ§é ã表ç¾ãã
ãã»Decoratorï¼ããã¤ã³ã¹ã¿ã³ã¹ã«å¯¾ããåçã«ä»å æ©è½ã追å ãã
ãã»Facadeï¼è¤æ°ã®ãµãã·ã¹ãã ã®çªå£ã¨ãªãå
±éã®ã¤ã³ã¿ãã§ã¼ã¹ãæä¾ãã
ãã»Flyweightï¼å¤æ°ã®ã¤ã³ã¹ã¿ã³ã¹ãå
±æããã¤ã³ã¹ã¿ã³ã¹ã®æ§ç¯ã®ããã®è² è·ãæ¸ãã
ãã»Proxyï¼å
±éã®ã¤ã³ã¿ãã§ã¼ã¹ãæã¤ã¤ã³ã¹ã¿ã³ã¹ãå
å
ããå©ç¨è
ããã®ã¢ã¯ã»ã¹ã代çãããWrapperã¨ãå¼ã°ãã
âæ¯ãèãã«é¢ãããã¿ã¼ã³
ãã»Chain of Responsibilityï¼ã¤ãã³ãã®éåä¿¡ãè¡ãè¤æ°ã®ãªãã¸ã§ã¯ããéç¶ã«ã¤ãªãããããã®éãã¤ãã³ãã渡ããã¦ããããã«ãã
ãã»Commandï¼è¤æ°ã®ç°ãªãæä½ã«ã¤ãã¦ãããããã«å¯¾å¿ãããªãã¸ã§ã¯ããç¨æãããªãã¸ã§ã¯ããåãæ¿ãããã¨ã§ãæä½ã®åãæ¿ããå®ç¾ãã
ãã»Interpreterï¼æ§æ解æã®ããã«ãææ³è¦åãåæ ããã¯ã©ã¹æ§é ãä½ã
ãã»Iteratorï¼è¤æ°ã®è¦ç´ ãå
å
ãããªãã¸ã§ã¯ãã®ãã¹ã¦ã®è¦ç´ ã«å¯¾ãã¦ãé çªã«ã¢ã¯ã»ã¹ããæ¹æ³ãæä¾ãã
ãã»Mediatorï¼ãªãã¸ã§ã¯ãéã®ç¸äºä½ç¨ã仲ä»ãããªãã¸ã§ã¯ããå®ç¾©ãããªãã¸ã§ã¯ãéã®çµå度ãä½ããã
ãã»Mementoï¼ãã¼ã¿æ§é ã«å¯¾ããä¸é£ã®æä½ã®ãããããè¨é²ãã¦ããã以åã®ç¶æ
ã®å¾©å¸°ã¾ãã¯æä½ã®åç¾ãè¡ããããã«ãã
ãã»Observerï¼ã¤ã³ã¹ã¿ã³ã¹ã®å¤åãä»ã®ã¤ã³ã¹ã¿ã³ã¹ããç£è¦ã§ããããã«ãã
ãã»Stateï¼ãªãã¸ã§ã¯ãã®ç¶æ
ãå¤åããããã¨ã§ãå¦çå
容ãå¤ããããããã«ãã
ãã»Strategyï¼ãã¼ã¿æ§é ã«å¯¾ãã¦é©ç¨ããä¸é£ã®ã¢ã«ã´ãªãºã ãã«ãã»ã«åããã¢ã«ã´ãªãºã ã®åãæ¿ãã容æã«ãã
ãã»Template Methodï¼ã¢ã«ã´ãªãºã ã¯æ½è±¡ã¯ã©ã¹ã§ãå¦çå
容ã¯ãµãã¯ã©ã¹ã§å®ç¾©ãã
ãã»Visitorï¼ãã¼ã¿æ§é ãä¿æããã¯ã©ã¹ã¨ãããã«å¯¾ãã¦å¦çãè¡ãã¯ã©ã¹ãåé¢ãã
ä»åã¯ããVisitorãã¿ã¼ã³ãããã£ã¦ããã¾ãï¼
ãµã³ãã«ã³ã¼ãã®ç解
Visitorãã¿ã¼ã³ã§ã¯ããã¸ã¿ã¼ï¼è¨ªåè
ï¼ã¨ã¢ã¯ã»ãã¿ã¼ï¼åãå
¥ãå´ï¼ãåºã¦ãã¾ããã¢ã¯ã»ãã¿ã¼ã¯ accept()
ã¨ããã¡ã½ãããæã¡ããããå¤æ´ãããã¨ãªãããã¸ã¿ã¼ã®æ¯ãèããå¤æ´ãããã¨åºæ¥ãã®ãç¹å¾´ã§ãã
ã§ã¯ãå®éã«ããµã³ãã«ã³ã¼ããè¦ã¦ãããã¨ã«ãã¾ãã
ä»åã®PlantUMLã®ã¯ã©ã¹å³
PlantUMLã§ä½æããã¯ã©ã¹å³ã®ã³ã¼ãã¨ç»åãã¡ã¤ã«ã§ãã
@startuml
abstract Visitor {
+ {abstract} visit(File file)
+ {abstract} visit(Directory directory)
}
class ListVisitor {
- String currentdir
+ visit(File file)
+ visit(Directory directory)
}
Visitor <|-- ListVisitor
interface Element {
+ {abstract} void accept(Visitor v)
}
abstract Entry {
+ {abstract} String getName()
+ {abstract} int getSize()
+ String toString()
}
Element <|.. Entry
class File {
- String name
- int size
+ File()
+ String getName()
+ int getSize()
+ void accept(Visitor v)
}
Entry <|-- File
class Directory {
- String name
- List<Entry> directory
+ Directory()
+ String getName()
+ int getSize()
+ Entry add()
+ Iterator<Entry> iterator()
+ void accept(Visitor v)
}
Entry <|-- Directory
Iterable <|.. Directory
@enduml
Mainã¯ã©ã¹ï¼ä½¿ãå´ã®ã¯ã©ã¹ï¼
ã¾ãã¯ãVisitorãã¿ã¼ã³ããã©ã®ããã«ä½¿ãããã®ããè¦ãããã«ãMainã¯ã©ã¹ãè¦ã¦ããã¾ãã
åããããããªãã¨æãã®ã§ãå
ã«å®è¡çµæã示ãã¾ãã
public class Main {
public static void main(String[] args) {
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 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));
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());
}
}
å®è¡çµæ
ä»åã®ãµã³ãã«ã³ã¼ãã¯ããã¡ã¤ã«ã·ã¹ãã ãã¤ã¡ã¼ã¸ããã¢ããªã±ã¼ã·ã§ã³ã®ããã§ãããã¡ã¤ã«ã·ã¹ãã å´ãã¢ã¯ã»ãã¿ã¼ã§ããã£ã¬ã¯ããªãèµ°æ»ããã®ããã¸ã¿ã¼ã§ãã
ã¾ããrootãã£ã¬ã¯ããªãä½ãã¾ãããã®å¾ãrootãã£ã¬ã¯ããªã®ä¸ã«binãtmpãusrãã£ã¬ã¯ããªãä½ãã¾ãã
binãã£ã¬ã¯ããªã«ã10000ãã¤ãï¼ä»®ã«ãã¤ãã¨ããï¼ã®viãã¡ã¤ã«ã¨ã20000ãã¤ãã®latexãã¡ã¤ã«ãä½ãã¾ãã
ããã¾ã§ã§ããã¡ã¤ã«ã·ã¹ãã å´ï¼ã¢ã¯ã»ãã¿ã¼ï¼ã®æºåã¯å®äºã§ãããããããã«ã¼ããã£ã¬ã¯ããªã«å¯¾ãã¦ãèµ°æ»ï¼ãã¸ã¿ã¼ï¼ãéå§ãã¾ãã
ã¾ãããã¸ã¿ã¼ã¯ã訪åå
ã®rootãã£ã¬ã¯ããªã®æ
å ±ã表示ãã¾ãã訪åå
ã®ãã¹ã表示ãããµã¤ãºï¼rootãªã®ã§å
¨ãµã¤ãºï¼ã表示ãã¾ãã
次ã«ãrootãã£ã¬ã¯ããªå
ãèµ°æ»ãã¾ããbinãã£ã¬ã¯ããªãè¦ã¤ããã®ã§ãåãããã«è¨ªåå
ã®æ
å ±ã表示ããå¾ã次ã¯ãbinãã£ã¬ã¯ããªå
ãèµ°æ»ãã¾ããviãã¡ã¤ã«ãè¦ã¤ããã®ã§ããã¡ã¤ã«ã§ãã£ã¦ãåãããã«è¨ªåå
ã®æ
å ±ã表示ãã¾ãã
ãããç¹°ãè¿ãã¦ãå
¨ã¦ã®ãã£ã¬ã¯ããªããã¡ã¤ã«ã訪åãã¦ãã¾ãã
ãã®å¾ãããã«ãã£ã¬ã¯ããªãããã¡ã¤ã«ã追å ãã¦ãæå¾ã«ãå度ãrootãã£ã¬ã¯ããªããæä½ããã¦ãã¾ãã
å
¨ä½åã¯åãã£ã¦ããã®ã§ãä»åº¦ã¯ä¸èº«ãè¦ã¦ããã¾ãã
Visitorã¯ã©ã¹
Visitorã¯ã©ã¹ã¯ãæ½è±¡ã¯ã©ã¹ã§ãã
2ã¤ã®æ½è±¡ã¡ã½ãããå¤éå®ç¾©ï¼ãªã¼ãã¼ãã¼ãï¼ãã¦ãã¾ãã
public abstract class Visitor {
public abstract void visit(File file);
public abstract void visit(Directory directory);
}
次ã¯ãVisitorã¯ã©ã¹ãç¶æ¿ãã¦ããã¯ã©ã¹ãè¦ã¦ããã¾ãã
ListVisitorã¯ã©ã¹
Visitorã¯ã©ã¹ãç¶æ¿ããListVisitorã¯ã©ã¹ã§ãã
ãã©ã¤ãã¼ãã¡ã³ãå¤æ°ã¨ãã¦ãç¾å¨ã®ãã£ã¬ã¯ããªï¼ã«ã¬ã³ããã£ã¬ã¯ããªï¼ãæã£ã¦ãã¾ãã
visit(File file)
ã¯ããã¡ã¤ã«ã«è¨ªåããå ´åã®è¡åãå®è£
ãã¦ãã¦ããã¡ã¤ã«ã®çµ¶å¯¾ãã¹ã表示ãã¦ãã¾ããå¾ã§åºã¦ãã¾ãããfileãªãã¸ã§ã¯ãã¯æåååã®ã¨ãã¯ãµã¤ãºãä¸ç·ã«è¡¨ç¤ºãããããªå®è£
ã«ãªã£ã¦ãã¾ãã
visit(Directory directory)
ã¯ããã£ã¬ã¯ããªã«è¨ªåããå ´åã®è¡åãå®è£
ãã¦ãã¦ããã£ã¬ã¯ããªã®çµ¶å¯¾ãã¹ã表示ãã¦ãã¾ããfileãªãã¸ã§ã¯ãã¨åæ§ã«ãDirectoryãªãã¸ã§ã¯ãã¯æåååã®ã¨ãã«ãµã¤ãºãä¸ç·ã«è¡¨ç¤ºããå®è£
ã«ãªã£ã¦ãã¾ãã
ãã®å¾ããã®ãã£ã¬ã¯ããªãæã£ã¦ããè¦ç´ ï¼ãã£ã¬ã¯ããªããã¡ã¤ã«ï¼ãèµ°æ»ãã¦ããã¾ããèªåèªèº«ãä¸å±¤ã«ç§»åããã¦ãããããã§ã«ã¬ã³ããã£ã¬ã¯ããªãå¤åãã¦ããã®ã§ãç¾å¨ä½ç½®ãsavedirã«è¦ãã¦ããã¾ããä¸å±¤ã®èµ°æ»ãå®äºããã¨ãã«ã¬ã³ããã£ã¬ã¯ããªãå
ã«æ»ãã¦ãã¾ãã
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;
}
}
ããã¾ã§ããã¸ã¿ã¼ã¯ã©ã¹ã§ãã次ããã¯ã¢ã¯ã»ãã¿ã¼ã¯ã©ã¹ãè¦ã¦ããã¾ãã
Elementã¯ã©ã¹
Elementã¯ã©ã¹ã¯ãã¤ã³ã¿ã¼ãã§ã¼ã¹ã§ãã
1ã¤ã®æ½è±¡ã¡ã½ãããå®ç¾©ãã¦ãã¾ãããããã¢ã¯ã»ãã¿ã¼ã®ãã¸ã¿ã¼ãåãä»ããã¡ã½ããã«ãªãã¾ãã
public interface Element {
public abstract void accept(Visitor v);
}
Entryã¯ã©ã¹
Entryã¯ã©ã¹ã¯ãElementã¯ã©ã¹ã®ã¤ã³ã¿ãã§ã¼ã¹ãå®è£
ããæ½è±¡ã¯ã©ã¹ã§ãã
2ã¤ã®ã¡ã½ãããå®ç¾©ãã¦ããã®ã¨ãæåååã¡ã½ããããªã¼ãã¼ã©ã¤ããã¦ãã¾ããå
ã»ã©è¦ãããã«ãæåååã®ã¨ãã«ããµã¤ãºãåå¾ãã¦ãä¸ç·ã«è¡¨ç¤ºããããã«ãªã£ã¦ãã¾ãã
public abstract class Entry implements Element {
public abstract String getName();
public abstract int getSize();
@Override
public String toString() {
return getName() + " (" + getSize() + ")";
}
}
Fileã¯ã©ã¹
Entryã¯ã©ã¹ãç¶æ¿ããFileã¯ã©ã¹ã§ãã
ãã©ã¤ãã¼ãã¡ã³ãå¤æ°ã¨ãã¦ãname
ï¼ãã¡ã¤ã«åï¼ã¨ãsize
ï¼å®¹éï¼ãæã£ã¦ãã¾ãã
ã³ã³ã¹ãã©ã¯ã¿ã¯ããã©ã¤ãã¼ãã¡ã³ãå¤æ°ã®åæåãè¡ã£ã¦ãã¾ãã
getName()
ã¨ãgetSize()
ã¯ããã¡ã¤ã«åã¨å®¹éãåå¾ããã¡ã½ããã§ãã
accept()
ããä»åã®Visitorãã¿ã¼ã³ã®ãã¢ã§ãããã£ã¦ããã¨ã¯ããã¸ã¿ã¼ãªãã¸ã§ã¯ããå¼æ°ã§åãåãããã¸ã¿ã¼ãªãã¸ã§ã¯ãã®ã¡ã½ããã§ãã visit()
ã使ã£ã¦ãèªåèªèº«ï¼ã¢ã¯ã»ãã¿ã¼ï¼ã«è¨ªåããã¦ãã¾ãã
Visitorãã¿ã¼ã³ã§ã¯ãã¢ã¯ã»ãã¿ã¼ã® accept()
ãå¤æ´ãããã¨ãªãããã¸ã¿ã¼ã®æ¯ãèããå¤æ´ãããã¨ãåºæ¥ãã®ã§ããã確ãã«ãã¢ã¯ã»ãã¿ã¼ã®å®è£
ã¯å¤æ´ãä¸è¦ã§ããã¸ã¿ã¼å´ã®å®è£
ã§ãæ¯ãèããå¤æ´ã§ãããã§ãã
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 String getName() {
return name;
}
@Override
public int getSize() {
return size;
}
@Override
public void accept(Visitor v) {
v.visit(this);
}
}
Directoryã¯ã©ã¹
Fileã¯ã©ã¹ã¨åæ§ã«ãEntryã¯ã©ã¹ãç¶æ¿ããDirectoryã¯ã©ã¹ã§ããéç´ãªãã¸ã§ã¯ãã®ããã§ãIteratorã¤ã³ã¿ãã§ã¼ã¹ãå®è£
ãã¦ãã¾ãã
ãã©ã¤ãã¼ãã¡ã³ãå¤æ°ã¨ãã¦ãname
ï¼ãã¡ã¤ã«åï¼ã¨ãEntryã¯ã©ã¹ã®ãªãã¸ã§ã¯ããè¤æ°æ ¼ç´ã§ãããªã¹ãã® directory
ï¼ãã£ã¬ã¯ããªï¼ãæã£ã¦ãã¾ãã
ã³ã³ã¹ãã©ã¯ã¿ã¯ããã©ã¤ãã¼ãã¡ã³ãå¤æ°ã®åæåãè¡ã£ã¦ãã¾ãã
getName()
ã¨ãgetSize()
ã¯ããã¡ã¤ã«åã¨å®¹éãåå¾ããã¡ã½ããã§ããgetSize()
ã¯ãFileã¯ã©ã¹ã¨ç°ãªããå帰çã«ä¸å±¤ã®Entryã¯ã©ã¹ã®ãªãã¸ã§ã¯ãã®å®¹éãåå¾ãã¦ãã¾ããããã¯Iteratorãã¿ã¼ã³ã使ã£ã¦ãã¾ãã
add()
ã¯ããªã¹ãã«Entryã¯ã©ã¹ã®ãªãã¸ã§ã¯ãã追å ãã¦ãã¾ãã
iterator()
ã¯ãIteratorãã¿ã¼ã³ã®ããã«ãèªåèªèº«ã®Iteratorãè¿ãã¾ãã
accept()
ã¯ãFileã¯ã©ã¹ã¨åæ§ã§ãã
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Directory extends Entry implements Iterable<Entry> {
private String name;
private List<Entry> directory = new ArrayList<>();
public Directory(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public int getSize() {
int size = 0;
for (Entry entry: directory) {
size += entry.getSize();
}
return size;
}
public Entry add(Entry entry) {
directory.add(entry);
return this;
}
@Override
public Iterator<Entry> iterator() {
return directory.iterator();
}
@Override
public void accept(Visitor v) {
v.visit(this);
}
}
ãããã«
ä»åã¯Visitorãã¿ã¼ã³ãå¦ã³ã¾ããã
Visitorãã¿ã¼ã³ã®ãµã³ãã«ã³ã¼ãã¯ããã£ã¦ããã¨ãæ確ã§ãåãããããã£ãã§ããã
ã¢ã¯ã»ãã¿ã¼ãå¤æ´ããã«ãVisitorã¯ã©ã¹ãç¶æ¿ããã¯ã©ã¹ï¼ä»åã¯ListVisitorã¯ã©ã¹ã®ã¿ï¼ã®ãã¸ã¿ã¼ãå¥ã®ç¨éã§ä½ããã¨ãå¯è½ã«ãªã£ã¦ãã¾ããã
ä»åã¯ä»¥ä¸ã§ãï¼
æå¾ã¾ã§ãèªã¿ããã ãããããã¨ããããã¾ããã