Шаблоны проектирования - Шаблоны прототипов - Примеры использования в Java - Действия по отправке электронной почты на фестивале

Сцены

Примеры использования шаблона-прототипа шаблона-поверхностного клонирования и глубокого клонирования в Java:

Шаблоны проектирования — Шаблоны прототипов — Примеры поверхностного и глубокого клонирования в Java — Ищут программиста

Пример использования режима прототипа изначально записан выше, а праздничный день или событие — ниже.

Пример отправки писем.

шаблон прототипа

Простота шаблона прототипа (Prototype Pattern) уступает только шаблону singleton и шаблону iterator. Именно из-за своей простоты его можно использовать во многих сценариях.

Он определяется следующим образом:

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

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

Просто, так легко! Ядром режима прототипа является метод клонирования, с помощью которого объект копируется, а Java предоставляет интерфейс Cloneable для маркировки.

Этот объект можно копировать, почему он называется «маркировка»? Откройте справку JDK, чтобы увидеть, что у Cloneable нет метода, этот интерфейс — просто маркер,

Только объекты с этой меткой в ​​JVM могут быть скопированы. Итак, как мы можем преобразовать «возможно скопированное» в «можно скопировать»?

Метод заключается в переопределении метода clone(), да, вы правильно прочитали, переопределении метода clone().

Плюсы шаблона прототипа

Превосходное представление

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

Шаблон прототипа может лучше отражать его преимущества.

избежать ограничений конструктора

В этом его преимущество и недостаток, копируя прямо в память, конструктор выполняться не будет**. Преимущество в том, что ограничения уменьшаются,

Недостатком также является снижение ограничений, что необходимо учитывать в практических приложениях.

Сценарии использования шаблона прототипа

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

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

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

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

Сценарии с несколькими модификаторами для одного объекта

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

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

Затем он предоставляется вызывающей стороне фабричным методом.

Примечание о шаблоне прототипа

конструктор не будет выполнен

Класс A, реализующий Cloneable и переписывающий метод clone, имеет конструкцию без аргументов или конструкцию B с параметрами и генерирует объект S с помощью нового ключевого слова.

Затем с помощью S.clone() генерируется новый объект T, после чего конструктор B не будет выполняться при копировании объекта. Для получения подробной информации см. пример кода.

мелкая копия и глубокая копия

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

Предлагаемое решение состоит в том, чтобы реализовать глубокое копирование и поверхностное копирование отдельно.

Для поверхностного и глубокого копирования см. пример кода.

клон и два последних врага

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

Примечание:

Блог:
властный мошеннический темперамент blog_CSDN Blog-C#, Architecture Road, Blogger in SpringBoot

выполнить

1. Банковский фестиваль рассылает электронное письмо с уведомлением о розыгрыше.

Новый код шаблона рекламного письма

@Data
public class AdvTemplate {
    //广告信名称
    private String advSubject = "xx银行抽奖活动";
    //广告信内容
    private String advContext = "抽奖活动通知:......";
}

2. Новый код почтового класса

//邮件类代码
@Data
public class Mail {
    //收件人
    private String receiver;
    //邮件名称
    private String subject;
    //称谓
    private String appellation;
    //内容
    private String context;
    //邮件底部,一般是加上"xxx版权所有"等信息
    private String tail;
    public Mail(AdvTemplate advTemplate){
        this.context = advTemplate.getAdvContext();
        this.subject = advTemplate.getAdvSubject();
    }
}

3. Категория сцены

//场景类
public class Client {
    //发送账单的数量
    private static int MAX_COUNT = 6;

    public static void main(String[] args) {
        //模拟发送邮件
        int i =0;
        //把模板定义出来,这个一般从数据库中获取
        Mail mail = new Mail(new AdvTemplate());
        mail.setTail("badaoxxx版权所有");
        while (i<MAX_COUNT){
            //每封邮件不同的地方
            mail.setAppellation(i+"先生/女士");
            mail.setReceiver(i+"[email protected]");
            sendMail(mail);
            i++;
        }
    }

    public static void sendMail(Mail mail){
        System.out.println("标题:"+mail.getSubject()+"\t收件人:"+mail.getReceiver()+"\t...发送成功!");
    }
}

вопрос:

Для однопоточной отправки нужно изменить sendMail на многопоточность, и будут проблемы: первый почтовый объект будет сгенерирован и запущен в потоке 1, но еще не отправлен;

Также запускается поток 2, и получатель и заголовок почтового объекта меняются напрямую.Поток не является безопасным.Конечно, есть много других решений.

Один из них заключается в использовании шаблона нового типа для решения этой проблемы: через функцию копирования объекта для решения этой проблемы.

4. Модифицированный почтовый класс

//修改后的邮件类
@Data
public class MailExtend implements Cloneable{
    //收件人
    private String receiver;
    //邮件名称
    private String subject;
    //称谓
    private String appellation;
    //内容
    private String context;
    //邮件底部,一般是加上"xxx版权所有"等信息
    private String tail;
    public MailExtend(AdvTemplate advTemplate){
        this.context = advTemplate.getAdvContext();
        this.subject = advTemplate.getAdvSubject();
    }

    @Override
    public MailExtend clone() throws CloneNotSupportedException {
        MailExtend mailExtend = null;
        mailExtend = (MailExtend) super.clone();
        return mailExtend;
    }
}

5. Модифицированный класс сцены

//修改后的场景类
public class ClientExtend {
    //发送账单的数量
    private static int MAX_COUNT = 6;

    public static void main(String[] args) throws CloneNotSupportedException {
        //模拟发送邮件
        int i =0;
        //把模板定义出来,这个一般从数据库中获取
        MailExtend mail = new MailExtend(new AdvTemplate());
        mail.setTail("badaoxxx版权所有");
        while (i<MAX_COUNT){
            //每封邮件不同的地方
            MailExtend cloneMail = mail.clone();
            mail.setAppellation(i+"先生/女士");
            mail.setReceiver(i+"[email protected]");
            sendMail(cloneMail);
            i++;
        }
    }

    public static void sendMail(MailExtend mail){
        System.out.println("标题:"+mail.getSubject()+"\t收件人:"+mail.getReceiver()+"\t...发送成功!");
    }
}

Текущий результат остается неизменным, и это не имеет значения, даже если sendMail является многопоточным.

Функция mail.clone() в классе Client копирует объект для создания нового объекта, который совпадает с исходным объектом, а затем изменяет подробные данные.

Например, установка заголовка, адреса получателя и т. д. Этот режим, который не генерирует объект через ключевое слово new, а реализуется через копирование объекта, называется режимом прототипа.

6. Убедитесь, что конструктор после клонирования не будет выполняться

//构造函数不会被执行
public class Thing implements Cloneable{
    public Thing(){
        System.out.println("构造函数被执行了...");
    }

    @Override
    public Thing clone() throws CloneNotSupportedException {
        Thing thing = null;
        thing = (Thing)super.clone();
        return thing;
    }
}

Напишите другой клиент, чтобы скопировать объект

public class TestClient {
    public static void main(String[] args) throws CloneNotSupportedException {
        Thing thing = new Thing();
        Thing cloneThing = thing.clone();
    }
}

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

Принцип метода клонирования класса Object заключается в копировании из памяти в виде бинарного потока и перераспределении блока памяти.

7. Поверхностное и глубокое клонирование

См. пример поверхностного клонирования

public class QianClone implements Cloneable{
    //定义一个私有变量
    private ArrayList<String> arrayList = new ArrayList<>();
    @Override
    public QianClone clone() throws CloneNotSupportedException {
        QianClone thing = null;
        thing = (QianClone)super.clone();
        return thing;
    }
    public void setValue(String value){
        this.arrayList.add(value);
    }
    public ArrayList<String> getValue(){
        return this.arrayList;
    }
}

Класс сцены, называемый мелким клоном

public class QianCloneClient {
    public static void main(String[] args) throws CloneNotSupportedException {
        QianClone qianClone = new QianClone();
        qianClone.setValue("张三");
        QianClone qianCloneClone = qianClone.clone();
        qianCloneClone.setValue("李四");
        System.out.println(qianClone.getValue());
        //[张三, 李四]
    }
}

Добавьте приватную переменную arrayList, а затем запустите результат не только Чжан Сан, но и Ли Си.

Это связано с тем, что метод clone класса Object копирует только объект, а массивы и ссылочные объекты внутри объекта не копируются и по-прежнему указывают на внутренний адрес элемента исходного объекта.

Эта копия является поверхностной копией. Два объекта имеют общую частную переменную, и каждый может изменить ее, если вы ее измените. Итак, почему тип String можно использовать в классе Mail,

без проблем, вызванных мелкими копиями. Поскольку внутренние массивы и объекты не копируются, другие примитивные типы int, long, cha и т. д. и String будут скопированы.

Пример глубокого копирования

//深拷贝
public class ShenClone implements Cloneable{
    //定义一个私有变量
    private ArrayList<String> arrayList = new ArrayList<>();
    @Override
    public ShenClone clone() throws CloneNotSupportedException {
        ShenClone thing = null;
        thing = (ShenClone)super.clone();
        thing.arrayList = (ArrayList<String>) this.arrayList.clone();
        return thing;
    }
    public void setValue(String value){
        this.arrayList.add(value);
    }
    public ArrayList<String> getValue(){
        return this.arrayList;
    }
}

Класс сцены глубокого копирования

public class ShenCloneClient {
    public static void main(String[] args) throws CloneNotSupportedException {
        ShenClone shenClone = new ShenClone();
        shenClone.setValue("张三");
        ShenClone shenClone1 = shenClone.clone();
        shenClone1.setValue("李四");
        System.out.println(shenClone.getValue());
        //[张三]
    }
}

Делайте независимые копии частных переменных класса.

Этот метод реализует полную копию, между двумя объектами нет связи, и они не влияют друг на друга, это глубокая копия.

Supongo que te gusta

Origin blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/130337111
Recomendado
Clasificación