デザインパターン Zenデザインパターン - プロトタイプパターン
1: プロトタイプパターンの定義
プロトタイプ インスタンスを使用して、作成するオブジェクトのタイプを指定し、これらのプロトタイプをコピーして新しいオブジェクトを作成します。
プロトタイプ パターンの単純さは、シングルトン パターンとイテレータ パターンに次いで 2 番目です。シンプルだからこそ、さまざまなシーンで活用できます。
プロトタイプ モードの中核は、オブジェクトがコピーされる clone メソッドです。Java には、オブジェクトがコピー可能であることを示す Cloneable インターフェイスが用意されています。なぜそれが「マーキング」と呼ばれるのですか? Cloneable が何であるかを確認するには、JDK ヘルプを開いてください。メソッドはありません。このインターフェイスは単なるマークです。このマークが付いたオブジェクトのみが JVM にコピーできます。では、「コピーできる」から「コピーできる」に変換するにはどうすればよいでしょうか?その方法は、 clone() メソッドをオーバーライドすることです。はい、正しくお読みいただけます。clone() メソッドをオーバーライドすることです。 Mail クラスのクローン メソッドで上記を実行すると、このメソッドは Object オブジェクトのメソッドをオーバーライドします。
2: プロトタイプモードの利点
● 優れたパフォーマンス プロトタイプ モードはメモリ内のバイナリ ストリームのコピーであり、オブジェクトを直接新規作成するよりもパフォーマンスがはるかに優れています。特にループ内で多数のオブジェクトが生成される場合、プロトタイプ モードはそのパフォーマンスをよりよく反映できます。利点。
● コンストラクタの制約を回避する これは利点でもあり欠点でもあり、メモリに直接コピーすると、コンストラクタは実行されません (セクション 13.4 を参照)。利点は制約が減ることであり、欠点は制約も減ることであり、実際のアプリケーションではこれを考慮する必要があります。
3: プロトタイプモードの適用シナリオ
● リソース最適化シナリオ
クラスの初期化では、データ、ハードウェア リソースなど、多くのリソースを消化する必要があります。
● パフォーマンスとセキュリティ要件のあるシナリオ
new によるオブジェクトの生成に非常に面倒なデータの準備やアクセス許可が必要な場合は、プロトタイプ パターンを使用できます。
● オブジェクトに複数のモディファイアがあるシナリオ
オブジェクトが他のオブジェクトにアクセスできる必要があり、各呼び出し元がその値を変更する必要がある場合は、プロトタイプ パターンを使用して、呼び出し元が使用できるように複数のオブジェクトをコピーすることを検討できます。実際のプロジェクトでは、プロトタイプ パターンが単独で出現することは少なく、通常はファクトリ メソッド パターンと一緒に出現し、clone メソッドを通じてオブジェクトが作成され、ファクトリ メソッドによって呼び出し元に提供されます。プロトタイプ モードは Java と統合されており、誰でも使用できます。
4: プロトタイプモードに関する注意事項
构造函数不会被执行
浅いコピーに注意してください。浅いコピーによる問題が発生せずに、なぜ String 型を Mail クラスで使用できるのか疑問に思われるかもしれません? 内部配列と参照オブジェクトはコピーされず、int、long、char などの他のプリミティブ型はコピーされます。ただし、String 型の場合、Java はこれを基本型として考えてください。クローン メソッドがなく、処理メカニズムも非常に特殊です。文字列プールを介して必要な場合にのみメモリ内に作成されます。新しい型を使用するときは、 string の場合、リーダーは String を基本クラスとして使用できます。
プロトタイプ パターンを使用する場合、参照されるメンバー変数は、コピーされないように 2 つの条件を満たす必要があります: 1 つ目は、それらはメソッド内の変数ではなく、クラスのメンバー変数であること、2 つ目は、参照オブジェクトではなく、変更可能な参照オブジェクトであることプリミティブ型または不変オブジェクト。
ディープ コピーを実装するもう 1 つの方法は、オブジェクトを操作するためのバイナリ ストリームを自分で記述してから、オブジェクトのディープ コピーを実装することです。時間があれば、自分で実装することもできます。
特にクラスの継承に関しては、ディープ コピーとシャロー コピーを混合しないことをお勧めします。親クラスに複数の参照がある状況は非常に複雑です。推奨される解決策は、ディープ コピーとシャロー コピーを別々に実装することです。
5: クローンとフィアンルは二人の敵である
ディープ コピーを実現するという夢は、final キーワードの脅威によって打ち砕かれました。方法は常にあります。この方法を変更する方法を考えてみましょう。final キーワードを削除します。これが最も便利で安全かつ迅速な方法です。
clone メソッドを使用する場合は、クラスのメンバー変数に Final キーワードを追加しないでください。
6: プロトタイプパターンのベストプラクティス
これは次のように理解できます。オブジェクトの生成は最初から開始することはできませんが、既に特定のプロトタイプを持つオブジェクトから直接クローンを作成し、生産に必要なオブジェクトに変更することができます。言い換えれば、人を生み出すために、1歳から2歳、そして3歳へと成長する必要はありません。また、直接人を見つけて、その人からDNAを取得し、そのクローンを作成することもできます。を直接変更して 30 Years old! 私たちが話しているプロトタイプ モードにはこの機能があります。
7: 試作パターン例
【1】プロトタイプモードのテンプレート
1 package com.javagpt.design;
2 /**
3 * 邮件
4 * @author javagpt
5 *
6 * 原型模式:(1)实现Cloneable接口
7 * (2)重写Object的clone方法
8 */
9 public class Mail implements Cloneable{
10
11 private String name;
12
13 private String context;
14
15 private String title;
16
17 private String address;
18
19
20 public Mail(String name, String context, String title, String address) {
21 super();
22 this.name = name;
23 this.context = context;
24 this.title = title;
25 this.address = address;
26 }
27
28
29 /**
30 * 克隆方法
31 */
32 @Override
33 protected Mail clone() throws CloneNotSupportedException {
34 Mail mail1=null;
35 mail1=(Mail) super.clone();
36 return mail1;
37 }
38
39
40 public String getName() {
41 return name;
42 }
43
44 public void setName(String name) {
45 this.name = name;
46 }
47
48 public String getContext() {
49 return context;
50 }
51
52 public void setContext(String context) {
53 this.context = context;
54 }
55
56 public String getTitle() {
57 return title;
58 }
59
60 public void setTitle(String title) {
61 this.title = title;
62 }
63
64 public String getAddress() {
65 return address;
66 }
67
68 public void setAddress(String address) {
69 this.address = address;
70 }
71
72
73 }
【2】浅いコピー
1 package com.javagpt.design;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6
7
8 /**
9 * 浅拷贝
10 * @author javagpt
11 * (1)JVM做了一个偷懒的拷贝动作,Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象
12 的内部元素地址,这种拷贝就叫做浅拷贝
13 *(2)非常不安全
14 *
15 */
16 public class Thing implements Cloneable {
17
18 private List<String> list=new ArrayList<String>();
19
20
21 @Override
22 protected Thing clone() throws CloneNotSupportedException {
23 Thing thing=null;
24 thing=(Thing) super.clone();
25 return thing;
26 }
27
28 public List<String> getList() {
29 return list;
30 }
31
32 public void setList(String a) {
33 this.list.add(a);
34 }
35
36
37 }
【3】ディープコピー
1 package com.javagpt.design;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 /**
6 * 深层次拷贝
7 * (1)深拷贝还有一种实现方式就是通过自己写二进制流来操作对象,然后实现对象的深拷贝,这个大家有时间自己实现一下
8 * (2)深拷贝和浅拷贝建议不要混合使用,特别是在涉及类的继承时,父类有多个引用的情况就非常复杂,建议的方案是深拷贝和浅拷贝分开实现。
9 * @author javagpt
10 *
11 */
12 public class Thing2 implements Cloneable {
13 private ArrayList<String> list=new ArrayList<String>();
14
15
16 @Override
17 protected Thing2 clone() throws CloneNotSupportedException {
18 Thing2 thing2=null;
19 thing2=(Thing2) super.clone();
20 thing2.list=(ArrayList<String>) this.list.clone();
21 return thing2;
22 }
23
24 public List<String> getList() {
25 return list;
26 }
27
28 public void setList(String a) {
29 this.list.add(a);
30 }
31
32 }
【4】クライアントテスト
1 package com.javagpt.design;
2
3 import java.util.List;
4
5
6 public class ClientTest {
7
8 public static void main(String[] args) throws CloneNotSupportedException {
9 //test01();
10 //test02();
11 test03();
12 }
13
14 /**
15 * 原型模式:模板测试
16 * @throws CloneNotSupportedException
17 */
18 public static void test01() throws CloneNotSupportedException{
19 Mail mail=new Mail("javagpt", "go smx", "emailtojavagpt", "[email protected]");//ClientTest.main()com.javagpt.design.Mail@2a5330
20 System.out.println("ClientTest.main()"+mail.toString());
21 Mail mail2=mail.clone();
22 System.out.println("ClientTest.main()"+mail2.toString());//ClientTest.main()com.javagpt.design.Mail@18872380
23
24 }
25 /**
26 * 原型模式:浅拷贝
27 * @throws CloneNotSupportedException
28 */
29 public static void test02() throws CloneNotSupportedException{
30 Thing thing1=new Thing();
31 thing1.setList("小李");
32 Thing thing2=thing1.clone();
33 thing1.setList("小张");
34 List<String> t=thing1.getList();
35 List<String> t2=thing2.getList();
36 for (int i = 0; i < t.size(); i++) {
37 System.out.println("ClientTest.test02(t==>)"+t.get(i));
38 }
39 for (int i = 0; i < t2.size(); i++) {
40 System.out.println("ClientTest.test02(t2==>)"+t2.get(i));
41 }
42 //ClientTest.test02(t==>)小李
43 //ClientTest.test02(t==>)小张
44 //ClientTest.test02(t2==>)小李
45 //ClientTest.test02(t2==>)小张
46 }
47
48 /**
49 * 原型模式:深拷贝
50 * @throws CloneNotSupportedException
51 */
52 public static void test03() throws CloneNotSupportedException{
53 Thing2 thing2a=new Thing2();
54 thing2a.setList("小李");
55 Thing2 thing2b=thing2a.clone();
56 thing2a.setList("小张");
57 List<String> t=thing2a.getList();
58 List<String> t2=thing2b.getList();
59 for (int i = 0; i < t.size(); i++) {
60 System.out.println("ClientTest.test02(t==>)"+t.get(i));
61 }
62 for (int i = 0; i < t2.size(); i++) {
63 System.out.println("ClientTest.test02(t2==>)"+t2.get(i));
64 }
65 //ClientTest.test02(t==>)小李
66 //ClientTest.test02(t==>)小张
67 //ClientTest.test02(t2==>)小李
68 }
69 }
SenseTime 創設者、Tang Xiaoou 氏が 55 歳で死去 2023 年、PHP は停滞 Wi-Fi 7 が完全に利用可能になる2024 年初頭にデビュー、Wi-Fi 6 の 5 倍高速 Hongmeng システムが独立しつつあり、多くの大学が「Hongmeng クラス」を設立 Zhihui Jun の新興企業が借り換え、金額は 6 億元を超え、事前評価額は 35 億元 Quark Browser PC 版が内部テストを開始 AI コード アシスタントは人気があり、プログラミング言語のランキングはすべてです できることは何もありません Mate 60 Pro の 5G モデムと無線周波数技術ははるかに先を行っています MariaDB が SkySQL を分割し、確立されました独立した企業として</span> Xiaomi、Yu Chengdong 氏の Huawei からの「キールピボット」盗作声明に対応この記事は、ブログ投稿プラットフォーム OpenWrite によって公開されています。