プロトタイプモード
出典:https://github.com/GiraffePeng/design-patterns
1.定義
プロトタイプモデル(原型パターン)指定されたタイプのオブジェクトのインスタンスを作成し、プロトタイプをコピーして新しいオブジェクトを作成するために、プロトタイプを指します。
2、アプリケーションのシナリオ
プロトタイプモデルは、主に次のようなシナリオに適用されます。
- 1、クラスの初期化は、より多くのリソースを消費します。
- 2、作成された新しいオブジェクトは、非常に退屈なプロセス(データ準備、アクセス権など)が必要です
- 3、より複雑なコンストラクタ。
- 図4は、ループオブジェクトの多数を生成しました。
春では、プロトタイプモデルが広く使用され、例えばスコープ=「プロトタイプ」。JSON.parseObjectでは、多くの場合、()を使用しても、プロトタイプモデルです。
3、浅いクローン
インタフェースのプログラミングについて、聞かせてのはPrototypeInteface.javaインタフェースのクローンを作成します
public interface PrototypeInteface {
public PrototypeInteface clone();
}
PrototypeIntefaceは実装インタフェースは、cloneメソッドをオーバーライドすることをエンティティクラスを作成します。
public class ShallowPrototype implements PrototypeInteface{
private int id;
private String name;
private String type;
private List<String> arr;
public List<String> getArr() {
return arr;
}
public void setArr(List<String> arr) {
this.arr = arr;
}
public ShallowPrototype() {
super();
}
public ShallowPrototype(int id, String name, String type,List<String> arr) {
super();
this.id = id;
this.name = name;
this.type = type;
this.arr = arr;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public ShallowPrototype clone() {
ShallowPrototype shallowPrototype = new ShallowPrototype();
shallowPrototype.setId(this.id);
shallowPrototype.setName(this.name);
shallowPrototype.setType(this.type);
shallowPrototype.setArr(this.arr);
return shallowPrototype;
}
}
テストクラスを作成します。
public class PrototypeTest {
public static void main(String[] args) {
ShallowPrototype shallowPrototype = new ShallowPrototype(1, "name", "type",new ArrayList<String>() {{
add("测试");
}});
ShallowPrototype clone = shallowPrototype.clone();
System.out.println(shallowPrototype.getName() == clone.getName());
System.out.println(shallowPrototype.getArr() == clone.getArr());
clone.getArr().add("修改");
List<String> arr = shallowPrototype.getArr();
for (String string : arr) {
System.out.println(string);
}
}
}
ポストを実行するには、このコンソールを印刷:
true
true
测试
修改
テスト結果から、セットARRアドレスを参照先のレプリケーションは、値が、アドレス参照ではないことを意味し、同じです。我々は、オブジェクトのいずれかを変更する場合は、この場合には、基準値のデータ型ARR、shallowPrototypeおよびクローン(一覧)が変更されます。これは、私たちはしばしば浅いクローンと言うものです。データ値のちょうど完全なコピー、自身が新しい参照オブジェクトを作成するためにコピーされたオブジェクトへの参照はありません。換言すれば、参照されるオブジェクトの全ては依然として元のオブジェクトを指します。
JDKはまた、オブジェクトのクローンのデフォルトの方法を提供し、要件には、例えば、super.cloneの浅いクローンを実現することができるの呼び出し、単純にクローン化されたCloneableインタフェースクラス、クローンwriteメソッドを実装できます。
//实现Cloneable接口
public class PrototypeClone implements Cloneable{
private int id;
private String name;
private String type;
private List<String> arr;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<String> getArr() {
return arr;
}
public void setArr(List<String> arr) {
this.arr = arr;
}
public PrototypeClone(int id, String name, String type, List<String> arr) {
super();
this.id = id;
this.name = name;
this.type = type;
this.arr = arr;
}
public PrototypeClone clone() {
try {
//调用super.clone方法
return (PrototypeClone) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
テストクラスを作成します。
public class TestJdkClone {
public static void main(String[] args) {
PrototypeClone prototypeClone = new PrototypeClone(1, "123", "1", new ArrayList<String>() {{add("ceshi");}});
PrototypeClone clone = prototypeClone.clone();
System.out.println(prototypeClone.getArr() == clone.getArr());
}
}
結果を印刷します:
true
DESCRIPTIONクローンJDKの浅いクローンも提供されます。
4、深いクローニング
ディープクローンクローンは、ヒープメモリの特性の目的の一つ再オープン空間分布に対応する唯一の目標値ではなく、クローン化された参照アドレスです。
私たちの実装は、シリアライズとデシリアライズを使用して達成することができます。
また、インターフェイスを作成します。
public interface DeepCloneInterface {
public Object cloneObject();
}
実装クラスを作成し、(直列化復元のための)DeepCloneInterface直列化インターフェイスを実現
public class DeepPrototype implements DeepCloneInterface,Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int id;
private String name;
private List<String> arr;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getArr() {
return arr;
}
public void setArr(List<String> arr) {
this.arr = arr;
}
//序列化与反序列化实现深克隆
@Override
public Object cloneObject() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Object readObject = ois.readObject();
ois.close();
bis.close();
oos.flush();
oos.close();
bos.close();
return readObject;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
テストカテゴリ:
public class DeepTest {
public static void main(String[] args) {
DeepPrototype deepPrototype = new DeepPrototype();
deepPrototype.setArr(new ArrayList<String>() {{add("测试");}});
deepPrototype.setId(1);
deepPrototype.setName("测试");
DeepPrototype cloneObject = (DeepPrototype)deepPrototype.cloneObject();
System.out.println(cloneObject.getArr() == deepPrototype.getArr());
}
}
結果を印刷します:
false
深いクローン、クローンのみ値の下で見ることができ、そしてクローンにタイプが割り当てられている参照していません。
5、クローンダメージシングルトン
我々の目標のオブジェクトは、オブジェクトシングルトンクローンにある場合は、クローニングすることをその手段が深い一つのケースを弱体化されます。実際にソリューションをクローニング損傷の単一のケースを防ぐことは非常に簡単で、深い禁止クローニングすることができます。シングルトンクラスがCloneableインタフェースを実装しないか、または私達は次のように、単一の実施形態のクローンメソッドにオブジェクトを返すために、clone()メソッドを書き換えます。
....
@Override
protected Object clone() {
return 具体的单例实例对象;
}
....