プロトタイプモード
1.プロトタイプモード
プロトタイプモードは、それ自体をコピーすることによって作成されるオブジェクト作成モードです。
(1)プロトタイプモデルの特徴
- ターゲットオブジェクトは、プロトタイプオブジェクト自体によって作成されます。つまり、オブジェクト作成のアクションは、プロトタイプオブジェクト自体から送信されます。
- ターゲットオブジェクトは、プロトタイプオブジェクトのクローンです。Prottypeモードで作成されたオブジェクトは、ターゲットオブジェクトと同じ構造を持つだけでなく、ターゲットオブジェクトと同じ値を持ちます。
- オブジェクトのクローン作成のさまざまなディープレベルに応じて、浅いクローン作成と深いクローン作成があります
第二に、プロトタイプモードの具体的な実現
(1)クローン作成とコピーの違い
クローン作成とは、同じオブジェクト情報を持つ別のオブジェクトからオブジェクトをコピーすることを指し、それらのメモリアドレスは異なり、ヒープ内のオブジェクト情報は同じですが同じではありません。割り当てによって、変数間のメモリアドレスが変更されるだけです。
(2)クローンを作成するにはどうすればよいですか?
- ステップ1:クローン可能なインターフェースを実装する
- ステップ2:オブジェクトのclone()メソッドを書き直します
package 原型模式;
// 第一步实现Cloneable接口
public class Student implements Cloneable{
private int id;
private String name;
private String Sex;
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 getSex() {
return Sex;
}
public void setSex(String sex) {
Sex = sex;
}
// 重写Object中的clone()方法
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
}
それを呼んでください、クローンは成功していますか?
package 原型模式;
public class Maintest {
public static void main(String[] args) {
System.out.println(" 浅度克隆!");
Student s1 = new Student();
s1.setId(1);
s1.setName("张三");
s1.setSex("男");
System.out.printf("S1指向内存地址:"+s1+"----");
System.out.println("S1信息:"+"\tid:"+s1.getId()
+"\tname:"+s1.getName()+"\tsex"+s1.getSex());
/* 克隆s1 */
System.out.println("-----------------------------------------");
// s1要调用克隆方法
try {
Student s2 = s1.clone();
System.out.printf("S2指向内存地址:"+s2+"----");
System.out.println("S2信息:"+"\tid:"+s2.getId()
+"\tname:"+s2.getName()+"\tsex:"+s2.getSex());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
**印刷情報:**印刷情報では、S1とS2が指すメモリアドレスが異なり、2つのメモリアドレスに格納されている情報が同じであることがわかります。これはクローンであり、これは単なる浅いクローン!浅さは、基本的なデータ型のクローン作成のみを実現できますが、実現できません
ディープクローニング
最後のケースでは、浅いクローンの実装では、クローンも階層的であることがわかりました。浅いクローンは、基本データ型の属性に対してのみ有効であり、複合データ型には影響しません。ケースを見て、Student1のオブジェクトを作成し、配列属性を追加してから、オブジェクトのクローンを作成して、配列のアドレスが同じかどうかを確認しましょう。
package 原型模式;
import java.util.List;
//第一步实现Cloneable接口
public class Student1 implements Cloneable{
private String[] arr = new String[2];
public String[] getArr() {
return arr;
}
public void setArr(String[] arr) {
this.arr = arr;
}
// 重写Object中的clone()方法
@Override
protected Student1 clone() throws CloneNotSupportedException {
return (Student1) super.clone();
}
}
package 原型模式;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
Student1 s1 = new Student1();
String[] arr = new String[2];
arr[0]="数组";
arr[1]="数据";
s1.setArr(arr);
System.out.println("s1地址:"+s1);
System.out.println("s1数组地址:"+s1.getArr());
System.out.println("存储信息:"+s1.getArr()[0]+"、"+s1.getArr()[1]);
System.out.println("---------------------------------------------");
try {
Student1 s2 = s1.clone();
System.out.println("s2地址:"+s2);
System.out.println("s2-集合地址:"+s2.getArr());
System.out.println("存储信息:"+s2.getArr()[0]+"、"+s2.getArr()[1]);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
印刷結果:
これは
、メモリにディープクローン
を実装する方法です。実際、clone()メソッドを書き換えるときは、手動クローンを実行してから戻ります。
package 原型模式;
import java.util.List;
//第一步实现Cloneable接口
public class Student1 implements Cloneable{
private String[] arr = new String[2];
public String[] getArr() {
return arr;
}
public void setArr(String[] arr) {
this.arr = arr;
}
// 重写Object中的clone()方法
@Override
protected Student1 clone() throws CloneNotSupportedException {
// -------------------------实现深度克隆-----------------------
// 先拿到克隆对象
Student1 student =(Student1)super.clone();
// 然后进行手动克隆,自己进行循环赋值
// 先定义一个数组接受
String[] arr = new String[this.getArr().length];
// 对拷
for(int i = 0; i < arr.length; i++) {
arr[i] = this.getArr()[i];
}
student.setArr(arr);
return student;
// ---------------------------------------------------------
}
}
package 原型模式;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
Student1 s1 = new Student1();
String[] arr = new String[2];
arr[0]="数组";
arr[1]="数据";
s1.setArr(arr);
System.out.println("s1地址:"+s1);
System.out.println("s1数组地址:"+s1.getArr());
System.out.println("存储信息:"+s1.getArr()[0]+"、"+s1.getArr()[1]);
System.out.println("---------------------------------------------");
try {
Student1 s2 = s1.clone();
System.out.println("s2地址:"+s2);
System.out.println("s2-集合地址:"+s2.getArr());
System.out.println("存储信息:"+s2.getArr()[0]+"、"+s2.getArr()[1]);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
3つ目は、プロトタイプモデルの長所と短所です。
(1)プロトタイプモデルの利点
- cloneメソッドは、メモリブロックを直接コピーする仮想マシンによって実行されるため、新しいメソッドを使用してオブジェクトを作成するよりも高速です。
- 作成されたオブジェクトインスタンスがより複雑な場合、プロトタイプモードを使用すると、オブジェクト作成のプロセスを簡素化できます。
- オブジェクトのタイプと状態は、実行時に動的に取得してオブジェクトを作成できます。
(2)プロトタイプモデルのデメリット
- 各クラスにクローン作成メソッドを装備する必要があり、クローン作成メソッドはこのクラスにあります。既存のクラスを変更すると、ソースコードを変更する必要があり、開封率の原則に違反します。
- ディープクローニングを実装する場合は、より複雑なコードを記述する必要があります。オブジェクト間にネストされた参照が複数ある場合、ディープクローニングを実現するには、オブジェクトの各レイヤーのクラスがディープクローニングをサポートする必要があります。これは、実装がより面倒です。