Builder と Abstract Factory

Builder と Abstract Factory
S. Yukita
[email protected]
1. Builder パターン
使われ所
• 大きなインスタンスを組み上げる場合。
• インスタンスの組み上げにパターンがある
とき,パターンをディレクタに固定する。
• 組み上げパターンに従って実際の仕事を
するのはBuilderインタフェース(抽象クラ
ス)を実装(具象化)するクラス。
デザインパターン 第4回
2
uses
Main
Director
builder
construct
例
題
の
ク
ラ
ス
図
TextBuilder
makeTitle
makeString
makeItems
getResult
デザインパターン 第4回
Builder
makeTitle
makeString
makeItems
getResult
HTMLBuilder
makeTitle
makeString
makeItems
getResult
3
Builder.java
public abstract class Builder {
public abstract void makeTitle(String title);
public abstract void makeString(String str);
public abstract void makeItems(String[] items);
public abstract Object getResult();
}
デザインパターン 第4回
4
TextBuilder.java (1)
public class TextBuilder extends Builder {
private StringBuffer buffer = new StringBuffer();
public void makeTitle(String title) {
buffer.append("==============================\n");
buffer.append("『" + title + "』\n");
buffer.append("\n");
}
デザインパターン 第4回
5
TextBuilder.java (2)
public void makeString(String str) {
buffer.append('■' + str + "\n");
buffer.append("\n");
}
デザインパターン 第4回
6
TextBuilder.java (3)
public void makeItems(String[] items) {
for (int i = 0; i < items.length; i++) {
buffer.append(" ・" + items[i] + "\n");
}
buffer.append("\n");
}
デザインパターン 第4回
7
TextBuilder.java (4)
public Object getResult() {
buffer.append("==============================\n");
return buffer.toString();
}
}
デザインパターン 第4回
8
HTMLBuilder.java (1)
import java.io.*;
public class HTMLBuilder extends Builder {
private String filename;
private PrintWriter writer;
デザインパターン 第4回
9
HTMLBuilder.java (2)
public void makeTitle(String title) {
filename = title + ".html";
try { writer =
new PrintWriter(new FileWriter(filename));
} catch (IOException e) {
e.printStackTrace();
}
writer.println(
"<html><head><title>" + title
+ "</title></head><body>");
writer.println("<h1>" + title + "</h1>");
}
デザインパターン 第4回
10
HTMLBuilder.java (3)
public void makeString(String str) {
writer.println("<p>" + str + "</p>");
}
public void makeItems(String[] items) {
writer.println("<ul>");
for (int i = 0; i < items.length; i++) {
writer.println("<li>" + items[i] + "</li>");
}
writer.println("</ul>");
}
デザインパターン 第4回
11
HTMLBuilder.java (4)
public Object getResult() {
writer.println("</body></html>");
writer.close();
return filename;
}
}
デザインパターン 第4回
12
Director.java (1)
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
デザインパターン 第4回
13
public Object construct() {
Director.java
(2)
builder.makeTitle("Greeting");
builder.makeString("朝から昼にかけて");
builder.makeItems(new String[]{
"おはようございます。",
"こんにちは。"
});
builder.makeString("夜に");
builder.makeItems(new String[]{
"こんばんは。",
"おやすみなさい。",
"さようなら。"
});
return builder.getResult();
}
}
デザインパターン 第4回
14
Main.java (1)
public class Main {
public static void main(String[] args) {
if (args.length != 1) {
usage();
System.exit(0);
}
デザインパターン 第4回
15
if (args[0].equals("plain")) {
Main.java (2)
Director director = new Director(
new TextBuilder());
String result = (String)director.construct();
System.out.println(result);
} else if (args[0].equals("html")) {
Director director = new Director(
new HTMLBuilder());
String filename = (String)director.construct();
System.out.println(filename + "が作成されました。");
} else { usage();
System.exit(0);
}
}
デザインパターン 第4回
16
Main.java (3)
public static void usage() {
System.out.println(
"Usage: java Main plain
プレーンテキストで文書作成");
System.out.println(
"Usage: java Main html
HTMLファイルで文書作成");
}
}
デザインパターン 第4回
17
実行結果(plain)
java Main plain
=================================
[Greeting]
■朝から昼にかけて
・おはようございます。
・こんにちは。
■夜に
・こんばんは。
・おやすみなさい。
・さようなら。
=================================
デザインパターン 第4回
18
実行結果(HTML)
java Main html
Greeting.htmlが作成されました。
<html><head><title>Greeting</title></head><body>
<h1>Greeting</h1>
<p>朝から昼にかけて</p>
<ul>
<li>おはようございます。</li>
<li>こんにちは。</li>
</ul>
<p>夜にかけて</p>
<ul>
<li>こんばんは。</li>
<li>おやすみなさい。</li>
<li>さようなら。</li>
</ul>
</body></html>
デザインパターン 第4回
19
パターン
uses
Client
Director
builder
construct
Builder
buildPart1
buildPart2
buildPart3
getResult
ConcreteBuilder
buildPart1
buildPart2
buildPart3
getResult
デザインパターン 第4回
20
Sequence 図
:Client
:Director
construct
:ConcreteBuilder
buildPart1
デザインパターン 第4回
21
2. Abstract Factory パターン
類似のパターンとの比較
• Builder パターンでは Builder の抽象メソッドを
Director が次々呼び出すことによって大きなイン
スタンスを部分を徐々に構築する。
• Abstract Factory パターンは,インスタンス群の生
成とそれらのネットワーク配線に力点をおく。イン
スタンス生成方法および配線方法を抽象化する。
• Factory Method パターンはインスタンス生成を環
境との配線とともに行う定石を抽象化している。
デザインパターン 第4回
22
例
題
の
ク
ラ
ス
図
(
抽
象
ク
ラ
ス
)
Item
caption
makeHTML
Link
url
tray
makeHTML
add
makeHTML
creates
Page
Tray
creates
Factory
getFactory
createLink
createTray
createPage
デザインパターン 第4回
title
author
content
add
output
makeHTML
creates
23
例
題
の
ク
ラ
ス
図
(
具
象
ク
ラ
ス
)
ListLink
ListTray
ListPage
makeHTML
makeHTML
makeHTML
creates
creates
ListFactory
createLink
createTray
createPage
デザインパターン 第4回
creates
24
Item.java
package factory;
public abstract class Item {
protected String caption;
public Item(String caption) {
this.caption = caption;
}
public abstract String makeHTML();
}
デザインパターン 第4回
25
Link.java
package factory;
public abstract class Link extends Item {
protected String url;
public Link(String caption, String url) {
super(caption);
this.url = url;
}
}
デザインパターン 第4回
26
Tray.java
package factory;
import java.util.Vector;
public abstract class Tray extends Item {
protected Vector tray = new Vector();
public Tray(String caption) {
super(caption);
}
public void add(Item item) {
tray.add(item);
}
}
デザインパターン 第4回
27
Page.java(1)
package factory;
import java.io.*;
import java.util.Vector;
public abstract class Page {
protected String title;
protected String author;
protected Vector content = new Vector();
デザインパターン 第4回
28
Page.java(2)
public Page(String title, String author) {
this.title = title;
this.author = author;
}
public void add(Item item) {
content.add(item);
}
デザインパターン 第4回
29
public void output() {
Page.java(3)
try {
String filename = title + ".html";
Writer writer = new FileWriter(filename);
writer.write(this.makeHTML());
writer.close();
System.out.println(filename + " を作成し
ました。");
} catch (IOException e)
{e.printStackTrace();}
}
デザインパターン 第4回
30
Page.java(4)
public abstract String makeHTML();
}
デザインパターン 第4回
31
Factory.java(1)
package factory;
public abstract class Factory {
public static Factory getFactory(String classname) {
Factory factory = null;
try {
factory = (Factory)Class.forName(classname).newInstance();
} catch (ClassNotFoundException e) {
System.err.println("クラス " + classname + " が見つかりま
せん。");
} catch (Exception e) {e.printStackTrace();}
return factory;
}
デザインパターン 第4回
32
Factory.java(2)
public abstract Link createLink(String caption,
String url);
public abstract Tray createTray(String caption);
public abstract Page createPage(String title,
String author);
}
デザインパターン 第4回
33
package listfactory;
ListLink.java
import factory.*;
public class ListLink extends Link {
public ListLink(String caption, String url) {
super(caption, url);
}
public String makeHTML() {
return " <li><a href=\"" + url + "\">" +
caption + "</a></li>\n";
}
}
デザインパターン 第4回
34
ListTray.java(1)
package listfactory;
import factory.*;
import java.util.Iterator;
public class ListTray extends Tray {
public ListTray(String caption) {
super(caption);
}
デザインパターン 第4回
35
public String makeHTML() {
ListTray.java(2)
StringBuffer buffer = new StringBuffer();
buffer.append("<li>\n"); buffer.append(caption + "\n");
buffer.append("<ul>\n");
Iterator it = tray.iterator();
while (it.hasNext()) {
Item item = (Item)it.next();
buffer.append(item.makeHTML());
}
buffer.append("</ul>\n"); buffer.append("</li>\n");
return buffer.toString();
}
}
デザインパターン 第4回
36
ListPage.java(1)
package listfactory;
import factory.*;
import java.util.Iterator;
public class ListPage extends Page {
public ListPage(String title, String author) {
super(title, author);
}
デザインパターン 第4回
37
ListPage.java(2)
public String makeHTML() {
StringBuffer buffer = new StringBuffer();
buffer.append("<html><head><title>"
+ title + "</title></head>\n");
buffer.append("<body>\n");
buffer.append("<h1>" + title + "</h1>\n");
buffer.append("<ul>\n");
デザインパターン 第4回
38
ListPage.java(3)
Iterator it = content.iterator();
while (it.hasNext()) {
Item item = (Item)it.next();
buffer.append(item.makeHTML());
}
デザインパターン 第4回
39
ListPage.java(4)
buffer.append("</ul>\n");
buffer.append("<hr><address>"
+ author + "</address>");
buffer.append("</body></html>\n");
return buffer.toString();
}
}
デザインパターン 第4回
40
ListFactory.java(1)
package listfactory;
import factory.*;
public class ListFactory extends Factory {
public Link createLink(String caption, String url){
return new ListLink(caption, url);
}
デザインパターン 第4回
41
ListFactory.java(2)
public Tray createTray(String caption) {
return new ListTray(caption);
}
public Page createPage(String title, String
author) {
return new ListPage(title, author);
}
}
デザインパターン 第4回
42
import factory.*;
Main.java(1)
public class Main {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Usage: java Main
class.name.of.ConcreteFactory");
System.out.println("Example 1: java
Main listfactory.ListFactory");
System.out.println("Example 2: java
Main tablefactory.TableFactory");
System.exit(0);
}
デザインパターン 第4回
43
Main.java(2)
Factory factory =Factory.getFactory(args[0]);
Link asahi = factory.createLink(“朝日新聞”,
"http://www.asahi.com/");
Link yomiuri = factory.createLink(“読売新聞”,
"http://www.yomiuri.co.jp/");
デザインパターン 第4回
44
Main.java(3)
Link us_yahoo = factory.createLink("Yahoo!",
"http://www.yahoo.com/");
Link jp_yahoo =factory.createLink("Yahoo!Japan",
"http://www.yahoo.co.jp/");
Link excite = factory.createLink("Excite",
"http://www.excite.com/");
Link google = factory.createLink("Google",
"http://www.google.com/");
デザインパターン 第4回
45
Main.java(4)
Tray traynews = factory.createTray("新聞");
traynews.add(asahi);
traynews.add(yomiuri);
Tray trayyahoo= factory.createTray("Yahoo!");
trayyahoo.add(us_yahoo);
trayyahoo.add(jp_yahoo);
デザインパターン 第4回
46
Main.java(5)
Tray traysearch =
factory.createTray("サーチエンジン");
traysearch.add(trayyahoo);
traysearch.add(excite);
traysearch.add(google);
デザインパターン 第4回
47
Main.java(6)
Page page = factory.createPage("LinkPage",
"結城 浩");
page.add(traynews);
page.add(traysearch);
page.output();
}
}
デザインパターン 第4回
48
実行方法
java Main listFactory.ListFactory
デザインパターン 第4回
49
生成されたHTMLをブラウザでみると
LinkPage
•新聞
•朝日新聞
•読売新聞
•サーチエンジン
•Yahoo!
•Yahoo!
•Yahoo!Japan
•Excite
•Google
デザインパターン 第4回
50
パターン
AbstractProduct1
excecuteA
excecuteB
AbstractFactory
creates
createProduct1
createProduct2
......
ConcreteProduct1
excecuteA
excecuteB
AbstractFactory
creates
createProduct1
createProduct2
......
デザインパターン 第4回
51
AbstractProduct1
Main
excecuteA
excecuteB
演出家
AbstractFactory
creates
createProduct1
createProduct2
......
役
ConcreteProduct1
excecuteA
excecuteB
ConcreteFactory
creates
たとえ話
役者
createProduct1
createProduct2
......
デザインパターン 第4回
52