デザインパターン学習メモ：「Abstract Factory」

## このパターンの目的
GoF本によると、「互いに関連したり依存し合うオブジェクト群を、その具象クラスを明確にせずに生成するためのインタフェースを提供する」となっている。

「オブジェクト群」というのがポイントで、このあとの例で言うと、「Markdownを生成するためのオブジェクト群」、「HTMLを生成するためのオブジェクト群」のように環境や設定によってオブジェクトを切り替えたい時に、このパターンは有効である。

オブジェクト群の実体化方法に関する規則はFactoryクラス内に隠蔽され、使用と生成を切り離すことが可能になる。

## 実装例

```java:Main.java
// 実行するためのクラス
public class Main {
	public static void main(String[] args) {
		Client client = new Client(new MarkdownFactory());
		client.outputText("Headline 1", "important text.");
	}
}
```

```java:Client.java
// factoryフィールドによって動作を切り替える
public class Client {
	public AbstractFactory factory;

	public Client(AbstractFactory factory) {
		this.factory = factory;
	}

	public String createText(String headlineText, String importantText) {
		Headline headline = factory.getHeadline();  // 注目
		StrongText strongText = factory.getStrongText();  // 注目

		System.out.println(headline.createHeadline(headlineText));
		System.out.println(strongText.createStrongText(importantText));
	}
}
```

```java:AbstractFactory.java
abstract public class AbstractFactory {
	abstract Headline getHeadline();
	abstract StrongText getStrongText();
}
```

```java:MarkdownFactory.java
public class MarkdownFactory extends AbstractFactory {

	@Override
	Headline getHeadline() {
		return new MarkdownHeadline();
	}

	@Override
	StrongText getStrongText() {
		return new MarkdownStrongText();
	}
}
```

```java:HtmlFactory.java
public class HtmlFactory extends AbstractFactory {

	@Override
	public Headline getHeadline() {
		return new HtmlHeadline();
	}

	@Override
	public StrongText getStrongText() {
		return new HtmlStrongText();
	}
}
```

```java:MarkdownHeadline.java
public class MarkdownHeadline implements Headline {

	@Override
	public String createHeadline(String string) {
		return "#" + string;
	}
}
```

```java:MarkdownStrongText.java
public class MarkdownStrongText implements StrongText {

	@Override
	public String createStrongText(String text) {
		return "**" + text +  "**";
	}
}
```

※`HtmlHeadline.java`と`MarkdownStrongText.java`のコードは割愛する

### 実行例
Mainクラスを実行した結果

```
#Headline 1
**important text.**
```

## Abstract Factoryパターンを使わないとどうなる？

Clientの外から`Headline`と`StrongText`を渡すなら、下記のようなコードになる。
各環境用のオブジェクト（Markdown用ならMarkdown用）を不整合なく保持するよう強制できていない。

```java:Client.java
public class Client {
	private Headline headline;
	private StrongText StrongText;

	public Client(Headline headline, StrongText strongText) {
		this.headline = headline;
		this.strongText = strongText;
	}

	public void outputText(String headlineText, String importantText) {
		System.out.println(headline.createHeadline(headlineText));
		System.out.println(strongText.createStrongText(importantText));
	}
}
```

そして、オブジェクト群の生成が使用者側に移り、使用する具象クラスと生成規則を知らなければいけなくなった。

```java:Main.java
// 実行するためのクラス
public class Main {
	public static void main(String[] args) {
		Headline headline = new MarkdownHeadline();
		StrongText strongText = new MarkdownStrongText();

		Client client = new Client(headline, strongText);
		client.outputText("Headline 1", "important text.");
	}
}
```

Abstract Factoryパターンによって隠蔽されていた部分が、外部へ漏れてしまった。

## 参考文献
 * エリック ガンマ、ラルフ ジョンソン、リチャード ヘルム、ジョン プリシディース（1999）『オブジェクト指向における再利用のためのデザインパターン　改訂版』本位田　真一 / 吉田　和樹 監訳、ソフトバンククリエイティブ
 * アラン・シャロウェイ、ジェームズ・R・トロット（2014）『デザインパターンととともに学ぶ　オブジェクト指向のこころ』村上雅章訳、丸善出版