AbstractFactoryパターン

###AbstractFactoryパターンとは
抽象的な部品を組み合わせて抽象的な製品を作る。
部品の具体的な実装には注目せず、インターフェース(API)に注目する。
そして、そのインターフェース(API)だけを使って部品を組み立て、製品をまとめる。

###AbstractProduct(抽象的な製品)の役
AbstractProduct役はAbstractFactory役によって作り出される抽象的な部品や製品のインターフェースを定める。

````java
package factory;

/**
 * HTMLのハイパーリンクを抽象的に表現したクラス
 *
 */
public abstract class Link extends Item{
	// リンクの飛び先のURL保持用
	protected String url;

	 public Link(String caption, String url) {
		 super(caption);
		 this.url = url;
	}
}
````

````java
package factory;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;

/**
 * HTMLページ全体を抽象的に表現したクラス
 *
 */
public abstract class Page {
	protected String title;
	protected String author;
	protected ArrayList<Item> content = new ArrayList<>();

	public Page(String title, String author) {
		this.title = title;
		this.author = author;
	}

	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();
}
````

````java
package factory;

import java.util.ArrayList;
/**
 * 複数のLinkやTrayを集めてひとまとまりにしたものを表すクラス
 *
 */
public abstract class Tray extends Item{
	protected ArrayList<Item> tray = new ArrayList<>();

	 public Tray(String caption) {
		 super(caption);
	}

	 public void add(Item item) {
		 tray.add(item);
	 }
}
````

###AbstractFactory(抽象的な工場)の役
AbstractFactory役はAbstractProduct役のインスタンスを作り出すためのインターフェースを定める。

````java
package factory;

/**
 * クラス名を指定して具体的な工場のインスタンを作成するクラス
 *
 */
public abstract class Factory {
	public static Factory getFactory(String className) {
		Factory factory = null;
		try {
			factory = (Factory)Class.forName(className).newInstance();
		} catch (ClassCastException e) {
			System.out.println("クラス " + className + "が見つかりません。");
		} catch (Exception 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(依頼者)の役
Client役はAbstractFactory役とAbstractProduct役のインターフェースだけを使って仕事を行う役。
Client役は具体的な部品や製品や工場については知らない。

````java
import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class Main {

	public static void main(String[] args) {

		if (args.length != 1) {
			System.out.println("Usage: java Main class.mame.of.ConcreateFactory");
			System.out.println("Example 1: java Main listfactory,ListFactory");
			System.out.println("Example 2: java Main tablefactory,TableFactory");
			System.exit(0);
		}

		Factory factory = Factory.getFactory(args[0]);

		Link asahi = factory.createLink("朝日新聞", "http://www.asahi.com/");
		Link yomiuri = factory.createLink("読売新聞", "http://www.yomiuri.co.jp/");

		Link usYahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
		Link jpYahoo = 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/");

		Tray trayNews = factory.createTray("新聞");
		trayNews.add(asahi);
		trayNews.add(yomiuri);

		Tray trayYahoo = factory.createTray("Yahoo!");
		trayYahoo.add(usYahoo);
		trayYahoo.add(jpYahoo);

		Tray traySearch = factory.createTray("サーチエンジン");
		traySearch.add(trayYahoo);
		traySearch.add(excite);
		traySearch.add(google);

		Page page = factory.createPage("LinkPage", "田中 太郎");
		page.add(trayNews);
		page.add(traySearch);
		page.output();
	}

}
````

###ConcreteProduct(具体的な製品)の役
ConcteteProduct役ではAbstract役のインターフェース(API)を実装する。

````java
package listFactory;

import 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";
	}

}
````

````java
package listFactory;

import java.util.Iterator;

import factory.Item;
import factory.Page;

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>" + title + "</title></head>\n");
		buffer.append("<body>\n");
		buffer.append("<h1>" + title + "</h1>\n");
		buffer.append("<ul>\n");
		Iterator<Item> it = content.iterator();
		while (it.hasNext()) {
			Item item = it.next();
			buffer.append(item.makeHtml());
		}
		buffer.append("</ul>\n");
		buffer.append("<hr><address>" + author + "</address>");
		buffer.append("</body></html>\n");
		return buffer.toString();
	}
}
````

````java
package listFactory;

import java.util.Iterator;

import factory.Item;
import factory.Tray;

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<Item> it = tray.iterator();
		while (it.hasNext()) {
			Item item = it.next();
			buffer.append(item.makeHtml());
		}
		buffer.append("</ul>\n");
		buffer.append("</li>\n");
		return buffer.toString();
	}
}
````

###ConcreteFactory(具体的な工場)の役
ConcreteFactory役ではAbstractFactory役のインターフェース(API)を定める。

````java
package listFactory;

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

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);
	}
}
````
###引数でtableFactory.TableFactoryを渡して実行して作成されたhtmlファイル
![スクリーンショット 2020-09-04 15.50.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197834/9749aa50-b20d-487c-1933-a03965f595e1.png)

###別の具体的な工場を追加する
工場を追加するのは簡単であった。
どのようなクラスを作り、どのようなメソッドを実装すれば良いかが明確なため。

````java
package tableFactory;

import factory.Link;

public class TableLink extends Link {

	public TableLink(String caption, String url) {
		super(caption, url);
	}

	@Override
	public String makeHtml() {
		return "<td><a href=\"" + url + "\">" + caption + "</a></td>\n";
	}
}
````

````java
package tableFactory;

import java.util.Iterator;

import factory.Item;
import factory.Page;

public class TablePage extends Page {

	public TablePage(String title, String author) {
		super(title, author);
	}

	@Override
	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("<table width=\"80%\" border=\"3\">\n");
		Iterator<Item> it = content.iterator();
		while (it.hasNext()) {
			Item item = it.next();
			buffer.append("<tr>" + item.makeHtml() + "</tr>");
		}
		buffer.append("</table>\n");
		buffer.append("<hr><address>" + author + "</address>");
		buffer.append("</body></html>\n");
		return buffer.toString();
	}
}
````
````java
package tableFactory;

import java.util.Iterator;

import factory.Item;
import factory.Tray;

public class TableTray extends Tray {

	public TableTray(String caption) {
		super(caption);
	}

	@Override
	public String makeHtml() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("<td>");
		buffer.append("<table width=\"100%\" border=\"1\"><tr>");
		buffer.append("<td bgcolor=\"#cccccc\" align=\"center\" colspan=\"" + tray.size() + "\"><b>" + caption + "</b></td>");
		buffer.append("</tr>\n");
		buffer.append("<tr>\n");
		Iterator<Item> it = tray.iterator();
		while (it.hasNext()) {
			Item item = it.next();
			buffer.append(item.makeHtml());
		}
		buffer.append("</tr></table>");
		buffer.append("</td>");
		return buffer.toString();
	}
}
````

````java
package tableFactory;

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class TableFactory extends Factory {

	@Override
	public Link createLink(String caption, String url) {
		return new TableLink(caption, url);
	}

	@Override
	public Tray createTray(String caption) {
		return new TableTray(caption);
	}

	@Override
	public Page createPage(String title, String author) {
		return new TablePage(title, author);
	}
}
````

Client役であるMainは全く変更せず、実行時の引数をtableFactory.TableFactoryにして実行して作成されたhtmlファイル

![スクリーンショット 2020-09-04 15.57.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197834/b29b1985-77ce-3c64-df65-3a2d405d1d96.png)

https://github.com/aki0207/abstractFactory

こちらを参考にさせていただきました。
<a href="https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030/ref=sr_1_1?ie=UTF8&qid=1454743284&sr=8-1&keywords=java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80">増補改訂版Java言語で学ぶデザインパターン入門</a>