2015年6月6日土曜日

1-4. Prototype パターン

プロトタイプとなるインスタンスを用いて作成するオブジェクトの種類を指定し、
このプロトタイプを複製することで新しいオブジェクトを生成します。



一般的にインスタンスの生成は、クラス名を指定して new し、必要に応じて初期化を行い
ます。
Prototype パターンでは、上記で生成したプロトタイプを複製し、必要に応じて
最小限の初期化することでインスタンスの生成を行います。
これにより、以下のメリットがあります。
・初期化処理のコストが高いときにそれを軽減できる
・基本クラスのインターフェースから複製を行う場合、実際の複製処理が派生クラスで
行われるため、直接派生クラスを指定する必要がない

一般的にインスタンスを生成するには、直接クラス名を指定して new します。
    ConcreteProduct product = new ConcreteProduct();
    product.init(); // 時間のかかる処理
Prototype パターンでは、あらかじめプロトタイプを作成しておき、それを複製することで
インスタンスの生成を行います。
    // プロトタイプを作成
    AbstractProduct prototype = new ConcreteProduct();
    prototype.init(); // 時間のかかる処理
    // プロトタイプからインスタンスを生成
    AbstractProduct product = prototype.clone();
    prototype.setValue(100); // 時間のかからない処理
これにより、複製処理のコストを軽減できます。
また上記では、基本クラス AbstractProduct#clone() を呼び出して複製を行っていますが、
実際の複製処理は派生クラス ConcreteProduct で行われます。これにより、
prototype を作成しておけば複製処理では実際の派生クラスを意識する必要がありません。

サンプルプログラムは、プロトタイプからインスタンスを生成するクライアントクラスを
介して、インスタンスを生成する例です。
出力結果:
    0 1 2 3 4 5 6 7 8 9 
package design_pattern;

/**
 * Prototype
 * GoF
 * プロトタイプとなるインスタンスを用いて作成するオブジェクトの種類を指定し、
 * このプロトタイプを複製することで新しいオブジェクトを生成します。
 * 
 * 一般的にインスタンスの生成は、クラス名を指定して new し、必要に応じて初期化を行い
 * ます。
 * Prototype パターンでは、上記で生成したプロトタイプを複製し、必要に応じて
 * 最小限の初期化することでインスタンスの生成を行います。
 * これにより、以下のメリットがあります。
 * ・初期化処理のコストが高いときにそれを軽減できる
 * ・基本クラスのインターフェースから複製を行う場合、実際の複製処理が派生クラスで
 * 行われるため、直接派生クラスを指定する必要がない
 * 
 * 一般的にインスタンスを生成するには、直接クラス名を指定して new します。
 * <pre>
 *     ConcreteProduct product = new ConcreteProduct();
 *     product.init(); // 時間のかかる処理
 * </pre>
 * Prototype パターンでは、あらかじめプロトタイプを作成しておき、それを複製することで
 * インスタンスの生成を行います。
 * <pre>
 *     // プロトタイプを作成
 *     AbstractProduct prototype = new ConcreteProduct();
 *     prototype.init(); // 時間のかかる処理
 *     // プロトタイプからインスタンスを生成
 *     AbstractProduct product = prototype.clone();
 *     prototype.setValue(100); // 時間のかからない処理
 * </pre>
 * これにより、複製処理のコストを軽減できます。
 * また上記では、基本クラス AbstractProduct#clone() を呼び出して複製を行っていますが、
 * 実際の複製処理は派生クラス ConcreteProduct で行われます。これにより、
 * prototype を作成しておけば複製処理では実際の派生クラスを意識する必要がありません。
 * 
 * サンプルプログラムは、プロトタイプからインスタンスを生成するクライアントクラスを
 * 介して、インスタンスを生成する例です。
 * 出力結果:
 * <pre>
 *     0 1 2 3 4 5 6 7 8 9 
 * </pre>
 * 
 * @author 2015/05/24 matsushima
 */
public class PrototypeSample {
	/**
	 * main
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		new PrototypeSample().client();
	}

	/**
	 * Client
	 */
	void client() {
		try {
			Client client = new Client(new ConcreatePrototype()); // プロトタイプ設定。
			for (int i = 0; i < 10; ++ i) {
				Prototype copy = client.copy(); // プロトタイプを複製してインスタンスを生成。
				copy.setValue(i);
				System.out.print(copy.getValue() + " ");
			}
			System.out.println();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}

	/** プロトタイプの抽象クラス。 */
	abstract class Prototype implements Cloneable {
		@Override
		public Object clone() throws CloneNotSupportedException {
			return super.clone(); // 実際の複製処理
		}
		public void init() {
			// 時間のかかる処理
		}
		public abstract void setValue(int value);
		public abstract int getValue();
	}

	/** プロトタイプクラス。 */
	class ConcreatePrototype extends Prototype {
		private int value;
		@Override
		public void setValue(int value) {
			this.value = value;
		}
		@Override
		public int getValue() {
			return this.value;
		}
	}

	/** プロトタイプからインスタンスを生成するクライアントクラス。 */
	class Client {
		private Prototype prototype;
		/** プロトタイプ設定。 */
		public Client(Prototype prototype) {
			this.prototype = prototype;
		}
		/** プロトタイプを複製してインスタンスを生成。 */
		public Prototype copy() throws CloneNotSupportedException {
			return (Prototype)prototype.clone();
		}
	}
}

0 件のコメント:

コメントを投稿