デザインパターン AbstractFactory:関連する部品を組み合わせる
概要
関連オブジェクト群の生成方法を抽象クラスだけで指定するパターン
具象側のオブジェクト群を入れ替える事でグループ単位での追加/修正が容易になる
クラス図
本例
抽象
AbstractProduct(製品)
public abstract class Item {
protected String caption;
public Item(String caption) {
this.caption = caption;
}
public abstract String makeHTML();
}
package abstractFactory.factory;
public abstract class Tray extends Item {
protected ArrayList<Item> tray = new ArrayList<Item>();
public Tray(String caption) {
super(caption);
}
public void add(Item item) {
this.tray.add(item);
}
}
package abstractFactory.factory;
public abstract class Link extends Item {
public Link(String caption, String url) {
super(caption);
this.url = url;
}
}
package abstractFactory.factory;
public abstract class Page {
protected String title;
protected String author;
protected ArrayList<Item> content = new ArrayList<Item>();
public Page(String title, String author) {
this.title = title;
this.author = author;
}
public void add(Item item) {
this.content.add(item);
}
public void output() {
try {
String filename = this.title + ".html";
Writer writer = new FileWriter(filename);
writer.write(this.makeHTML());
writer.close();
System.out.println(filename + "を作成");
} catch (IOException e) {
e.printStackTrace();
}
}
public abstract String makeHTML();
}
AbstractFactory(工場)
public abstract class Factory {
public static Factory getFactory(String classname) {
Factory factory = null;
try {
利用者から引数で指定されたクラス名(listfactory/ListFactory)をインスタンス化する
factory = (Factory) Class.forName(classname).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
return factory;
}
public abstract Link createLink(String caption, String url);
public abstract Tray createTray(String caption);
public abstract Page createPage(String title, String author);
}
Client(依頼者)
package abstractFactory;
public class Main {
public static void main(String[] args) {
if (args.length != 1) {
System.exit(0);
}
listfactory/ListFactoryのインスタンスを取得
Factory factory = Factory.getFactory(args[0]);
Link sankei = factory.createLink("産経新聞", "https://www.sankei.com/");
Link yomiuri = factory.createLink("読売新聞", "http://www.yomiuri.co.jp/");
Link yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
Link google = factory.createLink("Google", "http://www.google.com;");
Tray traynews = factory.createTray("新聞");
traynews.add(sankei);
traynews.add(yomiuri);
Tray trayweb = factory.createTray("WEB");
trayweb.add(yahoo);
trayweb.add(google);
Page page = factory.createPage("LinkPage", "株式会社米良太事務所");
page.add(traynews);
page.add(trayweb);
page.output();
}
}
結果
※ListPage部分
<html><head><title>LinkPage</title></head>
<body>
<h1>LinkPage</h1>
<ul>
※ListTray部分
<li>
新聞
<ul>
※ListLink部分
<li><a href="https://~">産経新聞</a></li>
<li><a href="http://~">読売新聞</a></li>
</ul>
</li>
※ListTray部分
<li>
WEB
<ul>
※ListLink部分
<li><a href="http://~">Yahoo!</a></li>
<li><a href="http://~;">Google</a></li>
</ul>
</li>
</ul>
<hr>
<address>株式会社米良太事務所</address>
</body>
</html>
具象
ConcreteProduct(製品)
依頼者は具象クラスしか参照しない
具象クラスは別途コンパイルが必要
public class ListLink extends Link {
public ListLink(String caption, String url) {
super(caption, url);
}
@Override
public String makeHTML() {
return "<li><a href=\"" + this.url + "\">" + this.caption + "</a></li>";
// <li><a href="this.url">this.caption</a></li>
}
}
package abstractFactory.listfactory;
public class ListTray extends Tray {
public ListTray(String caption) {
super(caption);
}
@Override
public String makeHTML() {
StringBuffer buffer = new StringBuffer();
buffer.append("<li>\n");
buffer.append(this.caption + "\n");
buffer.append("<ul>\n");
Iterator<Item> 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();
}
}
package abstractFactory.listfactory;
public class ListPage extends Page {
public ListPage(String title, String author) {
super(title, author);
}
@Override
public String makeHTML() {
StringBuffer buffer = new StringBuffer();
buffer.append("<html><head><title>" + this.title + "</title></head>\n");
buffer.append("<body>\n");
buffer.append("<h1>" + this.title + "</h1>\n");
buffer.append("<ul>\n");;
Iterator<Item> it = this.content.iterator();
while (it.hasNext()) {
Item item = (Item) it.next();
buffer.append(item.makeHTML());
Page、Tray、ListはmakeHTMLメソッドを実装しているのでどのオブジェクトでもHTMLが生成される
}
buffer.append("</ul>\n");
buffer.append("<hr><address>" + this.author + "</address>\n");
buffer.append("</body></html>\n");
return buffer.toString();
}
}
ConcreteFactory(工場)
public class ListFactory extends Factory {
@Override
public Link createLink(String caption, String url) {
return new ListLink(caption, url);
}
@Override
public Tray createTray(String caption) {
return new ListTray(caption);
}
@Override
public Page createPage(String title, String author) {
return new ListPage(title, author);
}
}