記事ディレクトリ
プロトタイプパターンとは
通常、 new something()メソッドを使用してインスタンスを作成しますが、次の状況ではこの方法での作成がサポートされない可能性があります。例えば:
- オブジェクトの種類が多く、1つのクラスにまとめることができない
オブジェクトの数が多すぎて処理できない 1つのクラスとして扱うと、多数のクラスファイルを作成する必要がある - クラスからインスタンスを生成するのが難しい
クラスのインスタンスを生成するプロセスが複雑すぎて、インスタンスからインスタンスを生成するのが困難です。たとえば、グラフィックス エディターでマウスを使用してグラフィックス インスタンスを作成する場合、前のユーザー操作で作成したインスタンスとまったく同じインスタンスを生成したい場合は、まず作成したインスタンスを保存し、次にコピーして新しいインスタンスを生成する - 生成されたインスタンスからフレームワークを分離したい、
インスタンスを生成するフレームワークが具象クラスに依存しないようにしたい。このとき、クラス名を指定してインスタンスを生成することはできませんが、事前にプロトタイプを登録し、そのインスタンスをコピーすることで新たなインスタンスを生成します。
デザイン パターンのうち、プロトタイプ パターンは、インスタンス プロトタイプとインスタンス モデルに基づいて新しいインスタンスを生成する創造的なデザイン パターンです。
クローン可能なインターフェースとクローンメソッド
Cloneableはマーカー インターフェイスです。このインターフェイスには抽象メソッドはありません。このインターフェイスを実装すると、このインターフェイスの実装クラスがCloneを使用できるようになります。
package java.lang;
public interface Cloneable {
}
CloneメソッドはObjectクラスのメソッドです。インスタンスを基にして新しいインスタンスをコピーできます。Objectクラスはすべてのクラスの親クラスであるため、すべてのクラスがCloneメソッドを持ちます。ただし、特定のクラスのインスタンスがこのメソッドを使用するには、クラスで最初に Cloneable インターフェイスを実装する必要があります。そうしないと、使用時にCloneNotSupportedExceptionがスローされます。
protected native Object clone() throws CloneNotSupportedException;
Cloneメソッドは、コピーされたインスタンスのフィールド値を新しいインスタンスに直接コピーする浅いコピーを実行します。たとえば、配列がフィールドに格納されている場合、Clone を使用してコピーすると、配列の参照のみがコピーされ、配列内の要素が 1 つずつコピーされるわけではありません。クローンが要件を満たせない場合は、クローンを書き換えることができます
例
文字列をボックスまたは下線で表示する例
マネジャー
package CreationPattern.PrototypeMode;
import java.util.HashMap;
/**
* 管理并复制实例
*/
public class Manager {
private HashMap map = new HashMap();
public void register(String name, Product proto) {
map.put(name, proto);
}
public Product create(String protoName) {
Product product = (Product) map.get(protoName);
return product.createClone();
}
}
製品
package CreationPattern.PrototypeMode;
/**
* 产品接口
*/
public interface Product extends Cloneable {
void use(String s);
Product createClone();
}
メッセージボックス
package CreationPattern.PrototypeMode;
/**
* 方框信息
*/
public class MessageBox implements Product {
private char decoChar;
public MessageBox(char decoChar) {
this.decoChar = decoChar;
}
@Override
public void use(String s) {
int len = s.getBytes().length;
for (int i = 0; i < len + 4; i++) {
System.out.print(decoChar);
}
System.out.println();
System.out.println(decoChar + " " + s + " " + decoChar);
for (int i = 0; i < len + 4; i++) {
System.out.print(decoChar);
}
System.out.println();
}
@Override
public Product createClone() {
Product p = null;
try {
p = (Product) clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
return p;
}
}
下線ペン
package CreationPattern.PrototypeMode;
/**
* 下划线信息
*/
public class UnderlinePen implements Product {
private char ulChar;
public UnderlinePen(char ulChar) {
this.ulChar = ulChar;
}
@Override
public void use(String s) {
int len = s.getBytes().length;
System.out.println("\"" + s + "\"");
for (int i = 0; i < len; i++) {
System.out.print(ulChar);
}
System.out.println();
}
@Override
public Product createClone() {
Product p = null;
try {
p = (Product) clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
return p;
}
}
結果
要約する
通常はnew something()を使ってインスタンスを生成しますが、この方法ではクラス名を指定する必要がありますが、クラス名を指定せずにインスタンスを生成する必要があったり、オブジェクトの種類が多かったりする場合もあります。または、フレームワークを分離してインスタンスを生成したい場合は、プロトタイプ モードを使用する必要があります。