[デザインモード]-プロトタイプモード

1.プロトタイプモードの概要

1.プロトタイプモードとは

プロトタイプモード(プロトタイプ)は、一種の作成設計モードです。通常、プロトタイプモードは、同じプロパティを持つオブジェクトを作成するために使用されます。これは、オブジェクトの作成プロセスをカプセル化するため、ビジネスの呼び出し元は詳細を気にする必要がなく、オブジェクト作成の原則。
プロトタイプモードは、それ自体がJava言語によって部分的に実装されている23の設計モードの中で最も単純なものである必要があるため、ほとんどの場合、それを使用するだけで済みます。

2.プロトタイプモードアプリケーションのビジネスシナリオ

プロトタイプモードは通常、同じオブジェクトの複数の複製を作成するために使用されます。オブジェクトの自己複製を実現するには、プロトタイプモードを使用する必要があることが理解できます。最も簡単な例を挙げると、西への旅のモンキーキングは猿の髪の毛で数千のモンキーキングになった、またはナルトのナルトは複数のシャドウクローンで複数のナルトに分割されました。プロトタイプモードは元のエンティティのコピーです。複数のオブジェクトを意味します。 。

第二に、プロトタイプモードの実現

1.プロトタイプモードの実現原理

Java言語を使用してプロトタイプモードを実装するのは非常に簡単です。Objectオブジェクトには独自のcloneメソッドがあるため、cloneメソッドを呼び出すだけで済みます。ここで、Objectオブジェクト自体はクローン可能なインターフェイスを実装していないため、cloneメソッドを使用する前に、プロトタイプオブジェクトのクローン可能なインターフェイスを実装する必要があることに注意してください。
ここに画像の説明を挿入

2.プロトタイプモードの簡単な実装

ここでは、孫悟空が猿の孫に変わることの実現を簡単にシミュレートします。

2.1プロトタイプオブジェクトを作成する

public class Monkey implements Cloneable {
    
    
	private String name;
	private String age;

	@Override
	protected Monkey clone() throws CloneNotSupportedException {
    
    
		// 这里先不修改浅拷贝相关代码
		return (Monkey) super.clone();
	}

	public Monkey(String name, String age) {
    
    
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString() {
    
    
		return "Monkey [name=" + name + ", age=" + age + "]";
	}

}

2.2プロトタイプオブジェクトのテスト

public class Test {
    
    

	public static void main(String[] args) throws CloneNotSupportedException {
    
    
		Monkey monkey = new Monkey("孙悟空", "三百四十二岁");
		Monkey clone = monkey.clone();
		System.out.println(monkey.equals(clone));
		System.out.println(clone.toString());
	}
}

テスト結果:
ここに画像の説明を挿入
ここでは、新しいオブジェクトが正常に作成されたことがわかりますが、実際にはまだ問題があります。次に、それについて詳しく説明します。

3.cloneメソッドを直接呼び出す際の問題

この時点で参照データ型の属性をエンティティに追加すると、この属性はcloneメソッドによってコピーされた後に新しいオブジェクトを作成しますか?ここでは、コードを変更し、一連の職業を追加し、パラメーター化された構築方法でデフォルトの割り当てを提供するだけです。

public class Monkey implements Cloneable {
    
    
	private String name;
	private String age;
	// 职业
	private List vocation;

	@Override
	protected Monkey clone() throws CloneNotSupportedException {
    
    
		// 这里先不修改浅拷贝相关代码
		return (Monkey) super.clone();
	}

	public Monkey(String name, String age) {
    
    
		super();
		this.name = name;
		this.age = age;
		this.vocation = new ArrayList<>();
	}

	@Override
	public String toString() {
    
    
		return "Monkey [name=" + name + ", age=" + age + ", vocation=" + vocation + "]";
	}

	public List getVocation() {
    
    
		return vocation;
	}

}

次に、結果を観察しましょう

public class Test {
    
    

	public static void main(String[] args) throws CloneNotSupportedException {
    
    
		Monkey monkey = new Monkey("孙悟空", "三百四十二岁");
		Monkey clone = monkey.clone();
		System.out.println(monkey.equals(clone));
		System.out.println(clone.getVocation().equals(monkey.getVocation()));

	}
}

ここに画像の説明を挿入
ここで、プロトタイプオブジェクトのListプロパティは、クローンオブジェクトのアドレスを再割り当てしませんが、プロトタイプオブジェクトとクローンオブジェクトは同じメモリ空間を共有するため、変数のセキュリティに深刻な問題が発生し、この問題が発生することは間違いありません。根本的な原因は、Objectのcloneメソッドがデフォルトでシャローコピーを実装していることです。この問題は、シャローコピーが参照型に遭遇したときに発生します。

3.ディープコピーとシャローコピー

1.ディープコピーとシャローコピーとは

浅いコピーとは、オブジェクトのクローンを作成するときに、オブジェクトの参照値のみをコピーすることを意味します。新しいオブジェクトと古いオブジェクトは同じメモリアドレスを共有するため、新しいオブジェクトの値が操作され、古いオブジェクトも操作できます。知覚される。JDK cloneメソッドは、デフォルトで実装の浅いコピーになります。
ディープコピーはシャローコピーとは異なります。ディープコピーは、新しいオブジェクト用に新しいメモリスペースを作成し、古い参照オブジェクトの変数の値を新しいオブジェクトに割り当てます。新しいオブジェクトと古いオブジェクトのメモリポイントは異なり、古いオブジェクトは新しいオブジェクトの値を認識しません。

2.ディープコピーを実装する方法

ディープコピーを実装するには、主に2つの方法があります。

  1. ダブルシャローコピー
  2. シリアル化と逆シリアル化

第四に、ディープコピープロトタイプモードの実現

1.ダブルシャローコピー

ダブルシャローコピーの実現は非常に簡単です。つまり、プロトタイプクラスで参照データ型のプロトタイプコピーを作成して、新しいメモリ参照を作成するという目的を達成します。

テストコード:

public class Monkey implements Cloneable {
    
    
	private static final String Monkey = null;
	private String name;
	private String age;
	// 职业
	private ArrayList vocation;

	@Override
	protected Monkey clone() throws CloneNotSupportedException {
    
    
		Monkey clone = (Monkey) super.clone();
		ArrayList copy = clone.getVocation();
		ArrayList shallowCopy = (ArrayList) copy.clone();
		ArrayList deepCopy = new ArrayList<>();
		deepCopy.add(shallowCopy);
		clone.setVocation(deepCopy);
		return clone;
	}

	public void setVocation(ArrayList vocation) {
    
    
		this.vocation = vocation;
	}

	public Monkey(String name, String age) {
    
    
		super();
		this.name = name;
		this.age = age;
		this.vocation = new ArrayList<String>();
		this.vocation.add("齐天大圣");
	}

	@Override
	public String toString() {
    
    
		return "Monkey [name=" + name + ", age=" + age + ", vocation=" + vocation + "]";
	}

	public ArrayList getVocation() {
    
    
		return vocation;
	}

}

演算結果:

public class Test {
    
    

	public static void main(String[] args) throws CloneNotSupportedException {
    
    
		Monkey monkey = new Monkey("孙悟空", "三百四十二岁");
		Monkey clone = monkey.clone();
		System.out.println(monkey.equals(clone));
		System.out.println(clone.getVocation().equals(monkey.getVocation()));

	}
}

ここに画像の説明を挿入
ここで、ダブルシャローコピー方式ではディープコピーを実現できますが、参照型が多すぎる場合は、参照型ごとに個別に処理する必要があることがわかりました。コードが煩雑で、日常の使用はお勧めしません。

2.Jsonシリアル化方法

Javaでシリアル化を実装する方法はたくさんあります。私は通常、シリアル化と逆シリアル化を実現するためにJsonオブジェクトを使用することを好みます。ここでは、Jsonツールキットを紹介する必要があります

public class Monkey implements Cloneable, Serializable {
    
    
	private static final String Monkey = null;
	private String name;
	private String age;
	// 职业
	private ArrayList<Object> vocation;

	@Override
	protected Monkey clone() throws CloneNotSupportedException {
    
    
		Monkey clone = (Monkey) super.clone();
		String jsonString = JSON.toJSONString(clone);
		Monkey parseObject = JSON.parseObject(jsonString, Monkey.class);
		return parseObject;

	}

	public Monkey() {
    
    
		super();
		// TODO Auto-generated constructor stub
	}

	public Monkey(String name, String age, ArrayList vocation) {
    
    
		super();
		this.name = name;
		this.age = age;
		this.vocation = vocation;
	}

	public String getName() {
    
    
		return name;
	}

	public void setName(String name) {
    
    
		this.name = name;
	}

	public String getAge() {
    
    
		return age;
	}

	public void setAge(String age) {
    
    
		this.age = age;
	}

	public ArrayList getVocation() {
    
    
		return vocation;
	}

	public void setVocation(ArrayList vocation) {
    
    
		this.vocation = vocation;
	}

	public static String getMonkey() {
    
    
		return Monkey;
	}

}

テストクラス:

public class Test {
    
    

	public static void main(String[] args) throws CloneNotSupportedException {
    
    
		ArrayList<Object> arrayList = new ArrayList<Object>();
		arrayList.add(new Object());
		Monkey monkey = new Monkey("孙悟空", "三百四十二岁", arrayList);
		Monkey clone = monkey.clone();
		System.out.println(monkey.equals(clone));
		System.out.println(clone.getVocation().equals(monkey.getVocation()));
		System.out.println(monkey.getVocation().hashCode());
		System.out.println(clone.getVocation().hashCode());

	}
}

試験結果:
ここに画像の説明を挿入

五数要約

1.プロトタイプモードの設計アイデア

ここに画像の説明を挿入

プロトタイプモードの実現アイデアは非常に単純です:

  1. クローン可能なインターフェースを継承する
  2. Objectクラスのcloneメソッドをコピーします
  3. ビジネスパーティは、プロトタイプクラスのcloneメソッドを呼び出すことができます

2.プロトタイプモデルの特徴

利点:

  1. パフォーマンスを向上させ、コンストラクターの制約を回避します

短所:

  1. クラス属性に特別な処理が必要な参照データ型が含まれていると、エラーが発生しやすくなります
  2. クローン可能なインターフェイスを実装する必要があるため、コードが複雑になります

これで本日の内容は終わりです。ご不明な点がございましたら、個人的にメッセージをお送りいただくか、コメント欄にメッセージを残していただければ、お早めにお答えいたします。やりがいを感じている友達は、3回連続でワンクリックを覚え、ブロガーに注意を払い、迷子にならないで、売春婦になることを拒否してください〜

おすすめ

転載: blog.csdn.net/xiaoai1994/article/details/112599634