デザインパターン入門 Prototype
概要
Prototypeパターンとは
- Prototype:"試作品"からインスタンスを生成する。クラスからではない。
- Cloneableインターフェースを実装し、自身からクローンを作成できる実体クラスがある。
ミソ
四角形を描くと言ったようなアクションが共通しているが、そのとき
- "/"で囲む四角形
- "*"で囲む四角形
- "x"で囲む四角形
と言ったような分かれ方をした3つの雛形があるとき、それぞれを別クラスで作っていてはキリが無い。
描く図形の形だけクラス分けをして、線の種類はClientにそれぞれ同一クラスとしてマッピングしておく。
そして同じ「"/"の線で三角形を描く」ことを繰り返すときは、雛形として登録したPrototypeインスタンスから新しいインスタンスをクローンして流用してやれば良い。
概念図
- Clientは Prototypeを呼び出す
- Prototypeを実装したConcretePrototypeが、createCloneによってクローンされる
実装 図形描画
登場人物
- frameworkパッケージ
- Productインターフェース: Cloneableを継承
- Managerクラス: CloneableをMapで格納、クローンを作成
- entityパッケージ
- Main: エントリポイント
- MessageBoxクラス: Productを実装。四角形を描画 / ConcreteProduct
- UnderLinePenクラス: Productを実装。下線を描画 / ConcreteProduct
実装 ソース
Product
Product
package prototype.product.frameworks;
public interface Product extends Cloneable{
public abstract void use(String s);
public abstract Product createClone();
}
Manager
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
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
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
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
}
}
実行結果
¥ Hello world ¥
xxxxxxxxxxxxxxx
***************
* Hello world *
***************
///////////////
/ Hello world /
///////////////
解釈
- ConcreteProductに描画する文字を設置
- ManagerのHashMapにConcreteProduct達を登録
- Manager.createでクローンを生成 → Product.createCloneが自身のクローンを返す
- Product.useで描画
実装 クラス図
- ProductがPrototypeの役割
- MessageBox, UnderLinePenがConcretePrototypeの役割
- ManagerがClientの役割
引用
増補改訂版 Java言語で学ぶデザインパターン入門 | 結城 浩 | コンピュータ・IT | Kindleストア | Amazon