Design Pattern | Abstract Factory Methods
Abstract Factoryパターンとは?
- Abstract Factoryは抽象工場という意味である。
- 抽象的であるとは、具体的にどのように実装されているかは考慮せず、インターフェースだけに注目している状態である。
- Abstract Factoryパターンは、部品の具体的な実装に注目せず、インターフェースに注目する。そして、そのインターフェースだけを使って部品を組み立て、製品としてまとめる方式である。
- 関連部品を組み合わせて製品を作るものである。
- GoFデザインパターンでは、生成に関するデザインパターンに分類される。
Abstract Factoryパターンのサンプルプログラム
お気に入り一覧をHTML形式で出力するサンプルプログラムである。
Class Diagram

1. Factoryクラス
抽象工場を代表するクラスである。Link、Tray、Pageを作る。
Factory.java
package com.devkuma.designpattern.creational.abstractfactory.factory;
public abstract class Factory {
public abstract Link createLink(String caption, String url);
public abstract Tray createTray(String caption);
public abstract Page createPage(String title);
public static Factory getFactory(String classname) {
Factory factory = null;
try {
factory = (Factory) Class.forName(classname).getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException e) {
System.err.println("클래스 " + classname + "를 찾을 수 없습니다.");
} catch (Exception e) {
e.printStackTrace();
}
return factory;
}
}
2. Itemクラス
LinkとTrayを統一的に扱うクラスである。
Item.java
package com.devkuma.designpattern.creational.abstractfactory.factory;
public abstract class Item {
protected String caption;
public Item(String caption) {
this.caption = caption;
}
public abstract String makeHTML();
}
3. Linkクラス
抽象部品: HTMLリンクを表すクラスである。
Link.java
package com.devkuma.designpattern.creational.abstractfactory.factory;
public abstract class Link extends Item {
protected String url;
public Link(String caption, String url) {
super(caption);
this.url = url;
}
}
4. Trayクラス
抽象部品: LinkとTrayを集めたクラスである。
Tray.java
package com.devkuma.designpattern.creational.abstractfactory.factory;
import java.util.ArrayList;
public abstract class Tray extends Item {
protected ArrayList tray = new ArrayList();
public Tray(String caption) {
super(caption);
}
public void add(Item item) {
tray.add(item);
}
}
5. Pageクラス
抽象部品: HTMLページを表すクラスである。
Page.java
package com.devkuma.designpattern.creational.abstractfactory.factory;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
public abstract class Page {
protected String title;
protected ArrayList content = new ArrayList();
public Page(String title) {
this.title = title;
}
public void add(Item item) {
content.add(item);
}
public void output() {
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();
}
}
public abstract String makeHTML();
}
6. ListFactoryクラス
具体的な工場を表すクラスである。ListLink、ListTray、ListPageを作る。
ListFactory.java
package com.devkuma.designpattern.creational.abstractfactory.listfactory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Factory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Link;
import com.devkuma.designpattern.creational.abstractfactory.factory.Page;
import com.devkuma.designpattern.creational.abstractfactory.factory.Tray;
public class ListFactory extends Factory {
public Link createLink(String caption, String url) {
return new ListLink(caption, url);
}
public Tray createTray(String caption) {
return new ListTray(caption);
}
public Page createPage(String title) {
return new ListPage(title);
}
}
7. ListLinkクラス
具体的な部品: HTMLリンクを表すクラスである。
ListLink.java
package com.devkuma.designpattern.creational.abstractfactory.listfactory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Link;
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";
}
}
8. ListTrayクラス
具体的な部品: LinkやTrayを集めたクラスである。
ListTray.java
package com.devkuma.designpattern.creational.abstractfactory.listfactory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Item;
import com.devkuma.designpattern.creational.abstractfactory.factory.Tray;
import java.util.Iterator;
public class ListTray extends Tray {
public ListTray(String caption) {
super(caption);
}
public String makeHTML() {
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();
}
}
9. ListPageクラス
具体的な部品: HTMLページを表すクラスである。
ListPage.java
package com.devkuma.designpattern.creational.abstractfactory.listfactory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Item;
import com.devkuma.designpattern.creational.abstractfactory.factory.Page;
import java.util.Iterator;
public class ListPage extends Page {
public ListPage(String title) {
super(title);
}
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");
Iterator it = content.iterator();
while (it.hasNext()) {
Item item = (Item) it.next();
buffer.append(item.makeHTML());
}
buffer.append("</ul>\n");
buffer.append("</body></html>\n");
return buffer.toString();
}
}
10. Mainクラス
メイン処理を実行するクラスである。
Main.java
package com.devkuma.designpattern.creational.abstractfactory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Factory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Link;
import com.devkuma.designpattern.creational.abstractfactory.factory.Page;
import com.devkuma.designpattern.creational.abstractfactory.factory.Tray;
public class Main {
public static void main(String[] args) {
Factory factory = Factory.getFactory("com.devkuma.designpattern.creational.abstractfactory.listfactory.ListFactory");
Link devkuma = factory.createLink("Devkuma", "https://www.devkuma.com//");
Link araikuma = factory.createLink("araikuma", "https://araikuma.tistory.com/");
Link naver = factory.createLink("Naver", "https://www.naver.com/");
Link daum = factory.createLink("Daum", "https://www.daum.com/");
Link google = factory.createLink("Google", "https://www.google.com/");
Tray pgTray = factory.createTray("프로그래밍");
pgTray.add(devkuma);
pgTray.add(araikuma);
Tray searchTray = factory.createTray("검색사이트");
searchTray.add(naver);
searchTray.add(daum);
searchTray.add(google);
Page page = factory.createPage("즐겨찾기");
page.add(pgTray);
page.add(searchTray);
page.output();
}
}
11. 実行結果
プログラムで生成したファイルは以下のとおりである。
즐겨찾기.html
<html><head><title>즐겨찾기</title></head>
<body>
<h1>즐겨찾기</h1>
<ul>
<li>
프로그래밍
<ul>
<li><a href="https://www.devkuma.com//">Devkuma</a></li>
<li><a href="https://araikuma.tistory.com/">araikuma</a></li>
</ul>
</li>
<li>
검색사이트
<ul>
<li><a href="https://www.naver.com/">Naver</a></li>
<li><a href="https://www.daum.com/">Daum</a></li>
<li><a href="https://www.google.com/">Google</a></li>
</ul>
</li>
</ul>
</body></html>
Abstract Factoryパターンのメリット
例えば、サンプルプログラムに新しい具体的な工場を追加する場合、Factory、Link、Tray、Pageのサブクラスを作り、それぞれの抽象メソッドを実装することになる。
つまり、factoryパッケージのクラスが持っている抽象部分を具体化していくだけである。このとき、どれだけ具体的な工場を追加しても、抽象工場を修正する必要はない。