デザインパターン入門　Prototype

# デザインパターン入門　Prototype



## 概要

Prototypeパターンとは

- Prototype:"試作品"からインスタンスを生成する。クラスからではない。
- Cloneableインターフェースを実装し、自身からクローンを作成できる実体クラスがある。



## ミソ



四角形を描くと言ったようなアクションが共通しているが、そのとき

- "/"で囲む四角形
- "*"で囲む四角形
- "x"で囲む四角形

と言ったような分かれ方をした3つの雛形があるとき、それぞれを別クラスで作っていてはキリが無い。

描く図形の形だけクラス分けをして、線の種類はClientにそれぞれ同一クラスとしてマッピングしておく。

そして同じ「"/"の線で三角形を描く」ことを繰り返すときは、雛形として登録したPrototypeインスタンスから新しいインスタンスをクローンして流用してやれば良い。





## 概念図
![concept.cld.jpg](https://qiita-image-store.s3.amazonaws.com/0/246573/1db61770-ae16-5d2f-7aa1-806c51a9bd5f.jpeg)


- Clientは Prototypeを呼び出す
- Prototypeを実装したConcretePrototypeが、createCloneによってクローンされる





## 実装 図形描画

登場人物

- frameworkパッケージ
  - Productインターフェース: Cloneableを継承
  - Managerクラス: CloneableをMapで格納、クローンを作成
- entityパッケージ
  - Main: エントリポイント
  - MessageBoxクラス: Productを実装。四角形を描画 / ConcreteProduct
  - UnderLinePenクラス: Productを実装。下線を描画 / ConcreteProduct





### 実装 ソース



Product

```java:Product
package prototype.product.frameworks;

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

}
```



Manager

```java
package prototype.product.frameworks;

import java.util.HashMap;

public class Manager {

	private HashMap<String, Cloneable> showcase = new HashMap<>();
	public void register(String name, Cloneable prototype) {
		showcase.put(name, prototype);
	}

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

}
```



MessageBox

```java
package prototype.product.entity;

import prototype.product.frameworks.Product;

public class MessageBox implements Product {
	private char decoChar;

	public MessageBox(char decoChar) {
		this.decoChar = decoChar;
	}

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

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



UnderLinePen

```java
package prototype.product.entity;

import prototype.product.frameworks.Product;

public class UnderLinePen implements Product{
	private char ulChar;
	public UnderLinePen(char ulChar) {
		this.ulChar = ulChar;
	}
	@Override
	public void use(String s) {
		int length = s.getBytes().length;
		System.out.println("¥ "+s+" ¥");
		for (int i = 0; i < length+4; i++) {
			System.out.print(ulChar);
		}
		System.out.println("");
	}

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

}
```



Main

```java
package prototype.product.entity;

import prototype.product.frameworks.Manager;
import prototype.product.frameworks.Product;

public class Main {
	public static void main(String[] args) {
		Manager manager = new Manager(); 
		UnderLinePen linePen = new UnderLinePen('x'); //1
		MessageBox mbox = new MessageBox('*'); //1 
		MessageBox sbox = new MessageBox('/'); //1
		manager.register("強調メッセージ", linePen);// 2
		manager.register("警告ボックス",mbox); //2
		manager.register("斜めボックス	", sbox);  //2

//		生成
		Product p1 = manager.create("強調メッセージ");//3
		p1.use("Hello world");   //4
		Product p2 = manager.create("警告ボックス"); //3
		p2.use("Hello world");   //4
		Product p3 = manager.create("斜めボックス	"); //3
		p3.use("Hello world");   //4
	}
}

```



実行結果

```bash
¥ Hello world ¥
xxxxxxxxxxxxxxx
***************
* Hello world *
***************
///////////////
/ Hello world /
///////////////
```



### 解釈

1. ConcreteProductに描画する文字を設置
2. ManagerのHashMapにConcreteProduct達を登録
3. Manager.createでクローンを生成　→ Product.createCloneが自身のクローンを返す
4. Product.useで描画



## 実装 クラス図
![classes.cld.jpg](https://qiita-image-store.s3.amazonaws.com/0/246573/f64fe6d2-dbad-17cd-2894-3de6232eedba.jpeg)


- ProductがPrototypeの役割
- MessageBox, UnderLinePenがConcretePrototypeの役割
- ManagerがClientの役割






## 引用

[増補改訂版 Java言語で学ぶデザインパターン入門 \| 結城 浩 \| コンピュータ・IT \| Kindleストア \| Amazon](https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88-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-%E7%B5%90%E5%9F%8E-%E6%B5%A9-ebook/dp/B00I8ATHGW)

[6\. Prototype パターン \| TECHSCORE\(テックスコア\)](https://www.techscore.com/tech/DesignPattern/Prototype.html/)