Prototype パターン

「Prototype」という英単語は、「原型」・「模範」を意味します。

javaでは、複製を作る操作を「Object」クラスが提供する「clone」メソッドを利用して行います。通常は、「クラス」から「オブジェクト」を作成という手順(newを用いて)となりますが、このパターンにおいては、「オブジェクト」から「オブジェクト」(複製)を作成します。


役割り

1. Client(利用者)
「ConcretePrototype」が実装しているオブジェクト複製メソッドを利用して、新しいオブジェクトを返します。
2. Prototype(原型)
オブジェクト複製メソッドのインタフェースを定義します。上記メソッドを「ConcretePrototype」で実装する際に「clone()」メソッドを使用する場合は、「Prototype」に「Cloneable」インタフェースを実装させます。
3. ConcretePrototype(具体的な原型)
自身のオブジェクトを複製するメソッドを実装します。
4. PrototypeUser(使用者)
「Prototype」パターンを適用したクラスを利用し処理します。

▲PageTop

クラス図

Prototypeパターンのクラス図

Prototypeパターン クラス図

▲PageTop

サンプル

ソースコード

1. Client.java

import java.util.Map;
import java.util.HashMap;

public class Client {
    private Map<String, Prototype> hashmap = new HashMap<String, Prototype>();
    public void regist(String key, Prototype prototype){
        hashmap.put(key, prototype);
    }
    public Prototype create(String key){
        Prototype prototype = hashmap.get(key);
        return prototype.createClone();
    }
}

2. Prototype.java

/** cloneメソッドを使用したい場合は、そのスーパークラス・インタフェースのどこかでCloneableインタフェースを実装していないといけません。
※ Cloneableインタフェースには抽象メソッドが1つも定義されていません。単にそのクラスが、cloneできるか否かのマーク付けをしているだけです。*/
public abstract class Prototype implements Cloneable {
public abstract Prototype createClone();
}

3. ConcretePrototype.java

public class ConcretePrototype extends Prototype {
    private int id;
    public ConcretePrototype(int id){
        this.id = id;
    }
    public Prototype createClone() {
        ConcretePrototype concretePrototype = null;
        try {
            concretePrototype = (ConcretePrototype)this.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return concretePrototype;
    }
    public int getId(){
        return id;
    }
}

4. PrototypeUser.java

public class PrototypeUser {
    public static void main (String[] args){
        Client client = new Client();
        ConcretePrototype cp1 = new ConcretePrototype(0);
        ConcretePrototype cp2 = new ConcretePrototype(1);
        ConcretePrototype cp3 = new ConcretePrototype(2);
        client.regist("0", cp1);
        client.regist("1", cp2);
        client.regist("2", cp3);
        Prototype prototype1 = client.create("0");
        Prototype prototype2 = client.create("1");
        Prototype prototype3 = client.create("2");
        System.out.println(((ConcretePrototype)prototype1).getId());
        System.out.println(((ConcretePrototype)prototype2).getId());
        System.out.println(((ConcretePrototype)prototype3).getId());
    }
}

実行結果

C:\sample\desin_pattern\prototype>javac PrototypeUser.java [Enter]

C:\sample\desin_pattern\prototype>java PrototypeUser [Enter]
0
1
2
        

▲PageTop

補足 オブジェクトの生成方法色々

オブジェクトの生成方法としては以下の様な方法があります。

1.「new」演算子を用いてオブジェクトを生成する方法

1番ポピュラーな生成方法です。

String str = new String();

2.「clone」メソッドを用いてオブジェクトを生成(コピー)する方法

java.lang.Objectオブジェクトが定義しているcloneメソッドを使用して自身のコピーを生成します。

※cloneメソッドを使用したい場合は、Cloneableインタフェースを実装しておく必要があります。

※コンストラクタは呼ばれません。

class A implements Cloneable {
    public Object copy(){
        A a = null;
        try {
            a = (A)clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return a;
    }
}

3.「newInstance」メソッドを用いてオブジェクトを生成する方法

java.lang.Classオブジェクトが定義しているnewInstanceメソッドを使用して、生成します。

※「InstantiationException」「IllegalAccessException」を例外として投げるので例外処理をしておく必要があります。

※引数なしコンストラクタ(デフォルト)が呼ばれます。


完全修飾クラス名を元にオブジェクトを生成します。

A a = (A)Class.forName("A").newInstance();

既に生成しているオブジェクトを元にオブジェクトを生成します。

A a = new A();
A b = a.getClass().newInstance();

▲PageTop