Шаблоны проектирования Zen Design Patterns — шаблоны прототипов

Шаблоны проектирования Zen Design Patterns — шаблоны прототипов

1: Определение шаблона прототипа

Используйте экземпляры прототипов, чтобы указать типы создаваемых объектов, и создавайте новые объекты, копируя эти прототипы.

По простоте паттерн «Прототип» уступает только паттерну «Одиночка» и паттерну «Итератор». Именно из-за своей простоты его можно использовать во многих сценариях.

​ Ядром режима прототипа является метод клонирования, с помощью которого объект копируется. Java предоставляет интерфейс Cloneable, указывающий, что объект можно копировать. Почему это называется «маркировкой»? Откройте справку JDK, чтобы узнать, что такое Cloneable. Метода нет.Этот интерфейс — просто метка.В JVM можно копировать только объекты с этой меткой. Итак, как мы можем преобразовать из «можно скопировать» в «можно скопировать»? Этот метод состоит в том, чтобы переопределить метод clone(). Да, вы правильно прочитали, это переопределить метод clone(). Взгляните на описанное выше в нашем методе клонирования класса Mail. Этот метод переопределяет метод объекта Object.

2. Преимущества режима прототипа

​ ● Отличная производительность ​ Режим прототипа представляет собой копию двоичного потока в памяти, которая имеет гораздо лучшую производительность, чем непосредственное создание нового объекта. Особенно, когда в цикле генерируется большое количество объектов, режим прототипа может лучше отразить его преимущества.

​ ● Выход из ограничений конструктора ​ Это одновременно и преимущество, и недостаток: при копировании непосредственно в память конструктор не будет выполнен (см. раздел 13.4). Преимущество состоит в том, что это уменьшает ограничения, а недостаток в том, что это также уменьшает ограничения, что необходимо учитывать в практических приложениях.

Третий: сценарии применения режима прототипа.

​ ● Сценарии оптимизации ресурсов

Инициализация класса требует обработки большого количества ресурсов, включая данные, аппаратные ресурсы и т. д.

​ ● Сценарии с требованиями к производительности и безопасности.

​ Если генерация объекта через new требует очень громоздкой подготовки данных или прав доступа, вы можете использовать шаблон прототипа.

​ ● Сценарии, в которых объект имеет несколько модификаторов.

Когда объект должен быть доступен другим объектам и каждому вызывающему объекту может потребоваться изменить его значение, вы можете рассмотреть возможность использования шаблона прототипа для копирования нескольких объектов для использования вызывающим объектом.​ В реальных проектах шаблон прототипа редко появляется один. Обычно он появляется вместе с шаблоном фабричного метода. Объект создается с помощью метода клонирования, а затем передается вызывающему объекту с помощью фабричного метода. Режим прототипа интегрирован с Java и может использоваться каждым.

Четвертое: что следует отметить в режиме прототипа

构造函数不会被执行 ​ Обратите внимание на неглубокий текст. Вы можете задаться вопросом, почему тип String можно использовать в классе Mail, не вызывая проблем, вызванных поверхностным копированием? Внутренние массивы и ссылочные объекты не копируются, а другие примитивные типы, такие как int, long, char и т. д., будут скопированы. но что касается типа String, Java хочет, чтобы вы думали о нем как о базовом типе. У него нет метода клонирования, а механизм обработки также совершенно особенный. Он создается в памяти только при необходимости через пул строк. При использовании нового string, читатели могут просто использовать String в качестве базового класса.

​ При использовании шаблона прототипа переменные-члены, на которые ссылаются, должны соответствовать двум условиям, чтобы они не были скопированы: во-первых, они являются переменными-членами класса, а не переменными внутри метода; во-вторых, они должны быть изменяемым ссылочным объектом, а не примитивный тип или неизменяемые объекты.

Другой способ реализации глубокого копирования — самостоятельно написать двоичный поток для управления объектом, а затем реализовать глубокую копию объекта. Если у вас есть время, вы можете реализовать его самостоятельно.

​ Рекомендуется не смешивать глубокое копирование и поверхностное копирование, особенно когда речь идет о наследовании классов. Ситуация, когда родительский класс имеет несколько ссылок, очень сложна. Рекомендуемое решение — реализовать глубокое и поверхностное копирование отдельно.

Пятое: клон и фианл — два врага

​ Ваша мечта реализовать глубокую копию была разбита угрозой конечного ключевого слова. Всегда есть способ. Давайте подумаем, как модифицировать этот метод: удалить последнее ключевое слово. Это самый удобный, безопасный и быстрый способ.

Если вы хотите использовать метод клонирования, не добавляйте ключевое слово Final к переменным-членам класса.

Шесть: лучшие практики шаблона прототипа

​ Это можно понять так: генерацию объекта можно не начинать с нуля, а можно клонировать непосредственно из объекта, уже имеющего определенный прототип, а затем модифицировать до объекта, необходимого для производства. Другими словами, чтобы произвести человека, вам не нужно расти с 1 года до 2 лет, а затем до 3 лет... Вы также можете напрямую найти человека, получить от него ДНК, а затем клонировать его. и напрямую измените его, чтобы ему исполнилось 30 лет! Режим прототипа, о котором мы говорим, имеет эту функцию.

Семь: пример шаблона-прототипа

【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 }

Эта статья опубликована на платформе блогов OpenWrite!

Тан Сяоу, основатель SenseTime, скончался в возрасте 55 лет. В 2023 году PHP застопорится. Wi-Fi 7 будет полностью доступен. в начале 2024 г. Дебют, в 5 раз быстрее, чем Wi-Fi 6. Система Hongmeng вот-вот станет независимой, и во многих университетах созданы «классы Hongmeng». Zhihui Стартап-компания Цзюня рефинансирует сумму, превышающую 600 миллионов юаней, а предварительная оценка составляет 3,5 миллиарда юаней. Версия Quark Browser для ПК начинает внутреннее тестирование AI code Assistant популярен, и рейтинги языков программирования высоки. Ничего не поделаешь Модем 5G и радиочастотная технология Mate 60 Pro далеко впереди MariaDB разделяет SkySQL и устанавливается как независимая компания Xiaomi отвечает на заявление Юй Чэндуна о плагиате со стороны Huawei
{{o.name}}
{{м.имя}}

рекомендация

отmy.oschina.net/u/5587102/blog/10142387