デザインパターン「Prototype」

# はじめに
本投稿は<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>のデザインパターンをまとめた記事です。今回はPrototypeパターンになります。
[まとめ一覧はこちら](#design_pattern)

# Prototypeパターン
<p align="center"><img width="350" alt="スクリーンショット 2016-02-14 15.31.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/e12b9d2b-50ef-5c8c-f9e3-22dacd1c85af.png"></p>



## Prototypeとは
Prototypeとはインスタンスを生成する時のデザインパターンで、***クラスからインスタンスを生成するのではなく、インスタンスから別のインスタンスを(コピーして)生成するパターン***のことです。

Prototypeと言う英単語の意味
###### <a href="http://ejje.weblio.jp/content/prototype" target="_blank">Weblio辞書参照</a>
> 原型、模範、原形

Prototypeの意味を見てわかるように単にインスタンスを生成するのではなく、原型や元となるインスタンスを元に新しいインスタンスを生成します。

## Prototypeパターンのクラス図
<p align="center"><img width="500" alt="スクリーンショット 2016-02-14 15.53.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/1b1d8c0c-b849-4e88-74ff-23be23e9f3eb.png"></p>

- ***Prototype***: インスタンスを複製して、新しいインスタンスを生成するメソッドを定める
- ***ConcretePrototype***: 実際にインスタンスを複製して、新しいインスタンスを生成するメソッドを実装
- ***Client***: 実際にインスタンスを複製して新しいインスタンスを生成する役割を担う

## 具体例
本書に記載されている例を参考に、与えた文字に対して下線を引いて表示するクラスと枠線で囲って表示するクラスを用いて紹介していきます

- Prototype: [Productインターフェイス](#product)
- ConcretePrototype:
 - [MessageBoxクラス](#message_box)(枠線で囲って表示)
 - [UnderLinePenクラス](#under_line)(下線表示)
- Client: [Managerクラス](#manager)


### Mainクラス
`use()`メソッドに渡した文字をクラスの生成時に渡した記号で、装飾しています

```java:Main.java
public static void main(String[] args) {
		
		Manager manager = new Manager();

		UnderLinepen upen = new UnderLinePen('-');
		MessageBox mbox = new MessageBox('@');
		MessageBox sbox = new MessageBox('♪');
		
		manager.register("stong message", upen);
		manager.register("warning box", mbox);
		manager.register("slash box", sbox);
		
		Product p1 = manager.create("stong message");
		p1.use("Git Hub");
		Product p2 = manager.create("warning box");
		p2.use("Qiita");
		Product p3 = manager.create("slash box");
		p3.use("Java");
}
```

### <a id="product">Productインターフェイス</a>
複製のためのメソッドを定めるインタフェース

```js
public interface Product extends Cloneable {
	
	public abstract void use(String s);
	public abstract Product createClone();
}
```

- `createClone()` 実際にインスタンスを複製する
- `use()`に文字列を渡すとその文字列を装飾して表示する

java.lang.Cloneableを継承していることで、`Clone()`メソッドでインスタンスを複製できます

<a href="https://docs.oracle.com/javase/7/docs/api/java/lang/Cloneable.html" target="_blank">Interface Cloneable</a>


### <a id="manager">Managerクラス</a>
Productインタフェースを利用してインスタンスの複製を行う

```java:Manager.java
public class Manager {
	private HashMap showcase = new HashMap();
	public void register(String name, Product prototype) {
		showcase.put(name, prototype);
	}

	public Product create(String protoname) {
        //※
		Product p = (Product)showcase.get(protoname);
		return p.createClone();
	}
}

```

- 複製元のインスタンスを保持しとくためのshowcaseを定義。

※Productのインスタンスをクローンすることで、クラス名に依存することなくProductインターフェイスを実装したクラスを利用することができる。


### <a id="message_box">MessageBoxクラス</a>

- 文字列の周りを枠線で囲む
- Productインターフェースを実装

```java:MessageBox.java
public class MessageBox implements Product {
	private char decoChar;
	public MessageBox(char decoChar) {
		this.decoChar = decoChar;
	}
	
    @Override
	public void use(String string) {
		int length = string.getBytes().length;
		for (int i = 0; i < length + 4; i++) {
			System.out.print(decoChar);
		}
		System.out.println("");
		System.out.println(decoChar + " " + string + " " + decoChar);
		
		for (int i = 0; i < length + 4; i++) {
			System.out.print(decoChar);
		}
		System.out.println("");
	}

    //Productインターフェイスを実装してなければCloneNotSupportedExceptionが投げられる
    @Override
	public Product createClone() {
		Product p = null;
		try {
			p = (Product)clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return p;
	}
}

```

### <a id="under_line">UnderLinePenクラス</a>

- 文字列に下線を表示
- Productインターフェースを実装

```java:UnderLinePen.java
public class UnderLinePen implements Product {
	private char ulChar;

	public UnderLinePen(char ulChar) {
		this.ulChar = ulChar;
	}

	@Override
	public void use(String string) {
		int length = string.getBytes().length;
		System.out.println(string);
		System.out.print("");
		for (int i = 0; i < length; i++) {
			System.out.print(ulChar);
		}
		System.out.println("");
		
	}

	@Override
	public Product createClone() {
		Product p = null;
		try {
			p = (Product)clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return p;
	}

}

```



## 実行結果

```java
Git Hub
-------
@@@@@@@@@
@ Qiita @
@@@@@@@@@
♪♪♪♪♪♪♪♪
♪ Java ♪
♪♪♪♪♪♪♪♪
```


# 追記

本書では以下のような場合にPrototypeパターンを利用すべきだと記述してあります

- 種類が多すぎてクラスにまとめられない場合
- クラスからのインスタンス生成が難しい場合
- フレームワークと生成するインスタンスを分けたい場合

例えば、図形を描くエディターのようなアプリケーションでは、図形をコピーして描画する機能があると思います。図形などをコピーする際は元の図形を「プロトタイプ」として登録し、コピーしたほうが簡単にできます。

- 状態を持つインスタンスをコピーするする場合のみ有用

無名クラスだとそもそも状態を持たないので複製する必要がない。無名クラスの場合はファクトリメソッドを使うべき

- <a href="http://futurismo.biz/archives/2800" target="_blank">状態ありはプロトタイプパターンで, 状態なしはファクトリメソッドで実装 (Java)</a>
- <a href="http://qiita.com/shoheiyokoyama/items/d752834a6a2e208b90ca" target="_blank">デザインパターン「Factory Method」</a>


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

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

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


# <a id="design_pattern">デザインパターン</a>

- 振る舞いに関するパターン
 - <a href="http://qiita.com/shoheiyokoyama/items/3f42d0057d9d5a861039" target="_blank">Iterator</a>
 - <a href="http://qiita.com/shoheiyokoyama/items/c2ce16b4f492cd014d50" target="_blank">Template Method</a>
 - <a href="http://qiita.com/shoheiyokoyama/items/d4b844ed29f84a80795b" target="_blank">Observer</a>
- 構造に関するパターン
 - <a href="http://qiita.com/shoheiyokoyama/items/bd1c692db480b640c976" target="_blank">Adapter</a>
- 生成に関するパターン
 - <a href="http://qiita.com/shoheiyokoyama/items/d752834a6a2e208b90ca" target="_blank">Factory Method</a> 
 - <a href="http://qiita.com/shoheiyokoyama/items/c16fd547a77773c0ccc1" target="_blank">Singleton</a>

# 参考文献
- <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.techscore.com/tech/DesignPattern/Prototype.html/" target="_blank">6. Prototype パターン | TECHSCORE(テックスコア)</a> 
- <a href="http://futurismo.biz/archives/2800" target="_blank">状態ありはプロトタイプパターンで, 状態なしはファクトリメソッドで実装 (Java)</a>