デザインパターン「Factory Method」

# はじめに
本投稿は<a href="http://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" target="_blank">Java言語で学ぶデザインパターン入門</a>のデザインパターンをまとめた記事です。今回はFactory Methodパターンになります。
[まとめ一覧はこちら](#design_pattern)

# Factory Methodパターン
<p align="center"><img width="442" alt="スクリーンショット 2016-02-14 15.31.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/da814940-7270-5a70-95ad-0bfb14e5cdd1.png"></p>


## Factory Methodとは
インスタンスの作り方をスーパークラスで定め、具体的な処理をサブクラスで行うパターンを***Factory Methodパターン***と呼びます。
オブジェクトの生成と具体的な処理を分離することで、より柔軟にオブジェクトを利用することができます。
<a href="http://qiita.com/shoheiyokoyama/items/c2ce16b4f492cd014d50" target="_blank">Template Methodパターン</a>をオブジェクト生成の場面に適応させたデザインパターンと言えますね。
簡単に言えば、***オブジェクト生成を容易にする***デザインパターンです。

### FactoryパターンとFactory Methodパターン

FactoryパターンとFactory Methodパターンでは以下の違いがあります
<dl>
 <dt>Factoryパターン</dt>
 <dd>Factoryクラスがオブジェクトの生成処理に加えて生成するオブジェクトの種類の変更をファクトリの処理の中で動的に行う</dd><br>
 <dt>Factory Methodパターン</dt>
 <dd>生成するオブジェクトごとにファクトリを用意することで、オブジェクトの生成処理を柔軟に行える</dd>
<dl/>

Factoryパターンでは、生成するオブジェクトの種類の増加や生成処理手順が複雑化に伴って、ファクトリ内の処理が冗長で複雑化してしまいます。
FactoryMethodパターンでは、サブクラスで生成処理を行うため生成処理を簡潔にすることができますが、生成するオブジェクトの種類を変更する場合、ファクトリクラスを切り替える必要があります。

実際には、オブジェクトのによって生成処理・手順を分岐するFactoryパターンの使用場面の方が多いですね。Factoryパターンの具体例については[後述](#factory_pattern)


## Factory Methodパターンのクラス図
<p align="center"><img width="550" alt="スクリーンショット 2016-02-14 15.53.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/6d44602b-5501-118b-ae71-85f914dddd6f.png"></p>

- 役割はインスタンス生成の為のCreatorと実際のオブジェクトのProductのみ
- 抽象クラスと並行したConcreteCreatorとConcreteProductの関係性が成り立つ

## 具体例

- 抽象クラス
 - Product :[Productクラス](#product)
 - Creator :[Factoryクラス](#factory)
- 具象クラス
 - ConcreteCreator :[AccountFactoryクラス](#account_factory)
 - ConcreteProduct :[Accountクラス](#account)

今回は、指定した名前のアカウントを生成する簡単な例で紹介していきます。

### Mainクラス
以下のように、`create`に名前を渡してやるだけで名前に応じたインスタンスを生成してくれるFactoryパターン実装していきます

```java:Main.java
public static void main(String[] args) {
        Factory factory  = new AccountFactory();
		Product account1 = factory.create("Ralph Johnson");
		Product account2 = factory.create("Richard Helm");
		Product account3 = factory.create("John Vlissides");
		Product account4 = factory.create("Erich Gamma");
		
		account1.use();
		account2.use();
		account3.use();
		account4.use();		
}
```

## 抽象クラス
### <a id="product">Productクラス</a>

`use`(誰のアカウントを使っているか)メソッドを宣言

```java:Product.java
public abstract class Product {

	public abstract void use();
}
```

### <a id="factory">Factoryクラス</a>

インスタンス生成の為の抽象クラス

```java:Factory.java
public abstract class Factory {
	
	public final Product create(String owner) {
		Product product = createProduct(owner);//※
		registerProduct(product);
		return product;
	}
	
	protected abstract Product createProduct(String owner);
	protected abstract void registerProduct(Product product);
}
```

※インスタンス生成をメソッドに任せることで、クラス名を指定する必要がなくなる
インスタンス生成については[後述](#ps)

## 具象クラス
### <a id="account_factory">AccountFactoryクラス</a>
- 抽象クラスの`createProduct`, `registerProduct`の処理を実装
- 生成した`Product(Account)`は`ArrayList`で管理

```java:AccountFactory.java
public class AccountFactory extends Factory {
	
	private List owners = new ArrayList();
	
	protected Product createProduct(String owner) {
		return new Account(owner);
	}
	
	protected void registerProduct(Product product) {
		owners.add( ((Account)product).getOwner() );
	}
	
	public List getOwners() {
		return owners;
	}
}
```

### <a id="account">Accountクラス</a>
インスタンス作成時と、`use`が呼び出された時にログを吐き出す

```java:Account.java
public class Account extends Product {
	
	private String owner;

	Account(String owner) {
		System.out.println("Create account: " + owner);
		this.owner = owner;
	}
	
	public void use() {
		System.out.println("Use account: " + owner);
	}
	public String getOwner() {
		return owner;
	}
}
```


## 実行結果

```java
Create account: Ralph Johnson
Create account: Richard Helm
Create account: John Vlissides
Create account: Erich Gamma
Use account: Ralph Johnson
Use account: Richard Helm
Use account: John Vlissides
Use account: Erich Gamma
```
名前に応じたインスタンスを生成できていることがわかりますね

# <a id="ps">追記</a>

- `Factory`の`createProduct`宣言でサブクラスによるインスタンス生成が期待されるが、具体例以外では以下の方法も考えられる
 - デフォルトの実装をする(サブクラスで実装されない時のため)
 - エラーの処理を書く(サブクラスで実装されなければ、エラーになる)

- 設計の意図を理解するためには、スーパークラスもサブクラス両方確認する必要がある
- インスタンスの管理が必要になるため、`ConcreteCreator`でSingletonパターンが適応される場合が多い

# <a id="factory_pattern">Factoryパターン</a>
Factoryパターンによるオブジェクト生成の分岐の例を紹介したいと思います。
<a href="http://www.nulab.co.jp/designPatterns/designPatterns2/designPatterns2-2.html" target="_blank">サルでもわかる 逆引きデザインパターン</a>の例がわかりやすかったので、データファイルの読み込みの例を紹介したいと思います。

まず、データファイルの読み込みの処理で言うと、CSV形式であれば`CSVDataReader`オブジェクトを、XML形式であれば`XMLDataReader`などと、使用者側からすればオブジェクトによって条件分岐したくないですよね。

```java
        AbstractDataReader reader = null;
		if (CSV == formatId) {
			reader = new CSVDataReaderd();
		} elseif (XML == formatId) {
			reader = new XMLDataReaderd();
		}
		data = reader.read();
```

使用者はオブジェクトの使用のみに専念したいですね。
Factoryパターンを適用すると以下のようになります。

```java:Factory.java
class Factory {
	AbstractDataReader create(int formatId) {
		AbstractDataReader reader = null;
		if (CSV == formatId) {
			reader = new CSVDataReaderd();
		} elseif (XML == formatId) {
			reader = new XMLDataReaderd();
		}
		return reader;
	}
}
```

Factoryクラスで生成処理を分離するだけで、以下のようになります。

```java
        AbstractDataReader reader = null;
		Factory factory = new Factory;
		reader = factory(formatId);
		data = reader.read();
```

使用者からしてみれば、オブジェクトの分岐や生成手順を気にする必要がなく、処理がかなり簡潔になりましたね。

新しいオブジェクトが増えた場合は、生成処理や条件式を`Factory`クラスに追加するだけでいいんですね。
重要な点は、***使用する側の処理を変更する必要がない***ところです。

### サンプルコードについて

以下のレポジトリにソースコードをアップしてあります。

[shoheiyokoyama/design-pattern_java](https://github.com/shoheiyokoyama/design-pattern_java/tree/master/FactoryMethod/com/shohei_yokoyama)


# <a id="design_pattern">デザインパターン</a>
- 生成に関するパターン
 - Abstract factory
 - Builder
 - <a href="http://qiita.com/shoheiyokoyama/items/d752834a6a2e208b90ca" target="_blank">Factory Method</a>
 - <a href="http://qiita.com/shoheiyokoyama/items/61826e158b3c4a259065" target="_blank">Prototype</a>
 - <a href="http://qiita.com/shoheiyokoyama/items/c16fd547a77773c0ccc1" target="_blank">Singleton</a>
- 構造に関するパターン
 - <a href="http://qiita.com/shoheiyokoyama/items/bd1c692db480b640c976" target="_blank">Adapter</a>
 - Bridge
 - Composite
 - Decorator
 - Facade
 - Flyweight
 - Proxy
- 振る舞いに関するパターン 
 - Chain of responsibility
 - Command
 - Interpreter
 - <a href="http://qiita.com/shoheiyokoyama/items/3f42d0057d9d5a861039" target="_blank">Iterator</a>
 - Mediator
 - Memento
 - <a href="http://qiita.com/shoheiyokoyama/items/d4b844ed29f84a80795b" target="_blank">Observer</a>
 - State
 - Strategy
 - <a href="http://qiita.com/shoheiyokoyama/items/c2ce16b4f492cd014d50" target="_blank">Template Method</a>
 - Visitor
 
# 参考文献
- <a href="http://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" target="_blank">Java言語で学ぶデザインパターン入門</a> 
- <a href="http://www.nulab.co.jp/designPatterns/designPatterns2/designPatterns2-1.html" target="_blank">サルでもわかる 逆引きデザインパターン</a>