デザインパターン入門 | Prototype(プロトタイプ)パターン

「Prototype(プロトタイプ)」パターンは、「インスタンスの複製を作る」デザインパターンです。

「複製元」となるインスタンスを作り、そのインスタンスをプロトタイプとして保存しておき、必要な時に複製を行って利用していきます。

それでは、「Prototype(プロトタイプ)」パターンの詳細について見ていきましょう。

「Prototype(プロトタイプ)」パターンの仕組み

「プロトタイプ」と聞くと「試作品」というイメージを持つ方もいるのではないでしょうか。

今回学ぶ「Prototype(プロトタイプ)」パターンでは、「原型・ひな型」という言葉のほうが適しているかもしれませんが、「インスタンスの複製元」と捉えていただくと良いかもしれません。

現実世界で「原型・ひな型」を考えていくと「金型」がイメージに近いのではないでしょうか。

「樹脂・プラスチック製品」の金型は、製品を作る際に必要となる「原型」と考えることができます。

今回は、「金型(Mold)」を管理するクラスと「製品(Product)」を表すクラスを元にご説明をしていきたいと思います。

今回作成するクラスの構成は下図のようになります。

プロトタイプ1

はじめに、「MoldManager」クラスは下記のようになります。(プログラム言語:Java)

package SamplePrototype;

import java.util.HashMap;

public class MoldManager {
	private HashMap productCollections = new HashMap();

	public void registerProduct(String productName, Cloneable product) {
		productCollections.put(productName, product);
	}

	public Product createProduct(String productName) {
		Product product = (Product) productCollections.get(productName);
		return product.getClone();
	}
}

このクラスには、

productCollectionsフィールド
プロトタイプを保存するためのハッシュマップ
registerProductメソッド
ハッシュマップにプロトタイプを登録する
createProductメソッド
登録されたプロトタイプから「インスタンスの複製」を生成する

が定義されています。

これらの具体的な使い方は、後ほど説明をしていきたいと思います。

そして、「Product」インターフェイスは、下記のようになります。

package SamplePrototype;

public interface Product extends Cloneable {
	public abstract Product getClone();
}

このインターフェイスは「Cloneable」インターフェースを実装していますが、「Cloneable」インターフェースに定義されているメソッドはありません。

「Cloneable」インターフェースは、「cloneメソッド」が使えることを示すためのインターフェースで、このようなインターフェースを「マーカーインターフェース」と呼ぶことがあります。

そして「Product」インターフェイスには、

getClone
「複製したインスタンス」を取得する抽象メソッド

が定義されています。

「Product」インターフェイスを実装した「具象クラス(ConcreteClass)」は、参考例として「プラモデル(PlasticModel)」「自動車部品(CarParts)」の2つを作成しています。

「プラモデル(PlasticModel)」クラスは、下記のようになります。

package SamplePrototype;

public class PlasticModel implements Product {
	private String name;
	private int price;

	public PlasticModel(String name, int price) {
		this.name = name;
		this.price = price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	@Override
	public Product getClone() {
		try {
			return (Product)clone();
		} catch ( Exception e ) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public String toString() {
		return "このプラモデルの名前は「" + this.name + "」です。価格は" + this.price + "円です。";
	}
}

そして、「自動車部品(CarParts)」クラスは下記のようになります。

package SamplePrototype;

public class CarParts implements Product {
	private String name;

	public CarParts(String name) {
		this.name = name;
	}

	public String getPartsName() {
		return this.name;
	}

	@Override
	public String toString() {
		return "この自動車部品の名前は【" + this.name + "】です。";
	}

	@Override
	public Product getClone() {
		try {
			return (Product)clone();
		} catch ( Exception e ) {
			e.printStackTrace();
		}
		return null;
	}
}

「getCloneメソッド」の中では、は、「clone」メソッドを実行し、登録されたインスタンスの複製を返すようになっています。

プログラムの実行例は下記のようになります。

package SamplePrototype;

public class Main {
	public static void main(String[] args) {
		// MoldManagerのインスタンスを生成
		MoldManager manager = new MoldManager();

		// PlasticModel(プラモデル)のインスタンスを生成
		PlasticModel plasticModel = new PlasticModel("タワー", 3800);

		// PlasticModel(プラモデル)の内容を出力
		System.out.println("【plasticModelの出力】");
		System.out.println(plasticModel);
		System.out.println("");

		// MoldManagerにインスタンスを登録
		manager.registerProduct("タワー", plasticModel);

		// MoldManagerに登録したオブジェクトのクローンを取得
		PlasticModel clonePlasticModel = (PlasticModel)manager.createProduct("タワー");

		// 価格の変更
		clonePlasticModel.setPrice(5000);

		// PlasticModel(プラモデル)のクローンの内容を出力
		System.out.println("【clonePlasticModelの出力】");
		System.out.println(clonePlasticModel);
		System.out.println("");

		// PlasticModel(プラモデル)の内容を出力
		System.out.println("【plasticModelの出力(確認用)】");
		System.out.println(plasticModel);
		System.out.println("");
	}
}

出力結果は、下記のようになります。

【plasticModelの出力】
このプラモデルの名前は「タワー」です。価格は3800円です。

【clonePlasticModelの出力】
このプラモデルの名前は「タワー」です。価格は5000円です。

【plasticModelの出力(確認用)】
このプラモデルの名前は「タワー」です。価格は3800円です。

上記の出力結果を見ると、「plasticModel」と「clonePlasticModel」は別のインスタンスであることがわかりますね。

このようにプロトタイプ(原型)となるインスタンスを登録しておいて、必要に応じて登録されたインスタンスの「クローン(複製)」を作り利用していくデザインパターンが、「Prototype(プロトタイプ)」パターンです。

「何かのインスタンス」を元にインスタンスを作りたい場合に利用できるデザインパターンですので、「どのような仕組みになっているのか」を理解し、プロトタイプパターンが使えるようになっていきましょう。

HOMEへ