设计模式之原型模式

2023-05-16

原型模式

  • 定义:指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
  • 不需要知道任何创建的细节,不需要调用构造函数
  • 类型:创建型

适用的场景

  • 类初始化消耗较多资源(比较重的对象)
  • new产生的一个对象需要非常频繁的过程(数据准备、访问权限等等)
  • 构造函数比较复杂
  • 循环体中生产大量的对象时

另外在软件系统中,有些对象的创建过程较为复杂,而且有时候需要频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的意图所在。

优点与缺点

优点:

  • 原型模式性能比直接new一个对象性能搞
  • 简化创建过程

clone通过复制对象的二进制流的方式来复制一个对象,因此免去了new对象时比较繁重的一些操作。
但克隆的方式有时会留下坑,这就是深克隆与浅克隆的区别,后面会举例子说明。
浅克隆是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。
深克隆不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象

缺点:

  • 必须配备克隆方法(java cloneable接口)
  • 对克隆复杂对象或者对克隆出的对象进行复杂改造,容易引入风险。

代码实现原型模式

要让对象具备克隆的能力,需要让类实现Cloneable接口,并重写Object类的clone方法。

//邮件实体类
public class Mail implements Cloneable {
    private String name;
    private String emailAddress;
    private String content;

    public Mail() {
        System.out.println("Mail Class Constructor");
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        System.out.println("clone mail object");
        return super.clone();
    }
}

//发送邮件的工具类
public class MailUtil {
    public static void sendMail(Mail mail) {
        String outputContent = "向{0}同学,邮件地址{1},邮件内容:{2}发送邮件。";
        System.out.println(MessageFormat.format(outputContent, mail.getName(), mail.getEmailAddress(), mail.getContent()));
    }

    public static void saveOriginMail(Mail mail) {
        System.out.println("存储originMail记录,origin Mail:"+mail.getContent());
    }
}

//test
 public static void main(String[] args) throws CloneNotSupportedException {
        Mail mail = new Mail();
        mail.setContent("初始化模板");
        for (int i = 0; i < 10; i++) {
            Mail tmp = (Mail) mail.clone();
            mail.setName("姓名"+i);
            mail.setEmailAddress("姓名"+i+"@qq.com");
            mail.setContent("恭喜你,中奖了!");
            MailUtil.sendMail(tmp);
        }
        MailUtil.saveOriginMail(mail);
    }

image.png
以上就完成一个简单的邮件克隆的demo。后面这个例子会演示浅克隆以及深克隆对程序的影响。

深克隆与浅克隆

public class Pig implements Cloneable {
    private String name;
    private Date birthday;

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Pig(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    //浅拷贝
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

//test
 public static void main(String[] args) throws CloneNotSupportedException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Date birthday = new Date(0L);
        Pig pig1 = new Pig("佩奇", birthday);
        Pig pig2 = (Pig) pig1.clone();
        birthday.setTime(System.currentTimeMillis());
        System.out.println("pig1 = " + pig1);
        System.out.println("pig2 = " + pig2);
    }

image.png
如果我们的本意是,希望复制出来的对象是在内存中独立的两个对象。那上面的这个克隆就出大问题了。很明显这就是一个浅克隆带来的问题。
问题就处在Pig类里的Date,这是个引用类型,在浅拷贝中,并不会对指针所指向的对象进行复制,而是复制了引用,实际的对象还是原来的那个对象。
我们可以使用debug追踪一下:
image.png
很明显,birthday引用指向的都是同一个对象。深拷贝也很简单,就是对引用类型也进行一次克隆:

 @Override
    protected Object clone() throws CloneNotSupportedException {
        Pig pig = (Pig) super.clone();
        Date date = (Date) pig.getBirthday().clone();
        pig.setBirthday(date);
        return pig;
    }

image.png
在使用原型模式,要合理地使用深拷贝和浅拷贝,避免踩坑!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式之原型模式 的相关文章

随机推荐

  • Python练习:四叶玫瑰数

    练习 xff1a 四叶玫瑰数 平台 xff1a Python123 io 教师 xff1a 嵩天 描述 四叶玫瑰数是4位数的自幂数 自幂数是指一个 n 位数 xff0c 它的每个位上的数字的 n 次幂之和等于它本身 xff08 例如 xff
  • 使用云服务器搭建Hexo个人博客

    彻底搞懂如何使用Hexo 43 GitHubPages搭建个人博客 讲解了如何使用Hexo 43 GitHubPages来搭建一款属于自己的个人博客 使用了一段时间后 xff0c 发现访问速度偏慢 xff0c 而且自己也在前段时间腾讯云做活
  • Python追赶法解方程组

    A 61 定义一个列表存储系数矩阵 L 61 U 61 Y 61 a 61 1 b 61 4 c 61 1 S 61 a S T 61 T R 61 R Answer X 61 N 61 5 X 61 39 x1 39 39 x2 39 3
  • 手把手教你安装Spring+搭建Spring开发环境

    为了让新手安装Spring时少走弯路 xff0c 小编写下详细步骤 xff08 以win8 xff0c 64位为例 xff09 请系好安全带 xff0c 坐好扶稳 一 xff1a 安装eclipse 如果已经安装请忽略此步 官网下载地址 x
  • 在Ubuntu上如果权限不够时,并且使用sudo还是权限不够,获得root权限

    如果用户具有sudo权限 xff0c 那么直接可以运行如下命令 xff1a sudo su root 输入当前用户的密码 passwd 输入密码 再次输入密码 退出root权限 按下ctrl 43 D
  • yum 安装libpcap

    针对于centos系统安装libpcap库命令 xff1a yum install libpcap yum install libpcap devel
  • 计算机网络自考2020,2020年8月自考02141计算机网络技术真题及答案

    以下是湖南自考生网为考生们整理的 2020年8月自考02141计算机网络技术真题及答案 xff0c 考生可通过自考历年真题练习更有把握的面对考试 xff0c 对题型更加熟悉 xff0c 从而取得更佳的成绩 供考生参考 2020年8月高等教育
  • DLL丢失一键修复

    DLL丢失一键修复 今天不小心删了DLL相关的库 xff0c 费了好久才搞好 xff0c 记录一下 原因 xff1a 删除了win10中的这些库 解决办法 xff1a 使用一键修复工具 DLL丢失一键修复工具 xff1a 获取工具
  • springmvc的配置文件详解

    springmvc xml需要配置的东西 配置controller扫描包 使用组件扫描器省去在spring容器配置每个Controller类的繁琐 使用context component scan自动扫描标记 64 Controller的控
  • Bug随手记----关于java.lang.IllegalStateException: The following classes could not be excluded because the

    Consider the following If you want an embedded database H2 HSQL or Derby please put it on the classpath If you have data
  • linux:Systemd使用(systemctl)

    系统服务管理工具systemd是为了便于linux用户操作系统服务的管理 xff0c systemd提供了systemctl命令工具进行systemd的各项操作 Systemd的版本 systemd version systemd和syst
  • C++面试宝典:进程间通讯方式概述

    1 管道 我们来看一条 Linux 的语句 netstat tulnp grep 8080 学过 Linux 命名的估计都懂这条语句的含义 xff0c 其中 是管道的意思 xff0c 它的作用就是把前一条命令的输出作为后一条命令的输入 在这
  • ubuntu16.04LTS更换阿里源

    sudo gedit etc apt sources list 替换 xff1a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 deb cdrom Ubuntu 16 04 LTS Xenial
  • a++多线程下出现消失的请求现象

    a 43 43 多线程下出现消失的请求现象 a 43 43 多线程下出现消失的请求现象是一个常见的多线程运行结果错误的例子 我们先来看一下a 43 43 代码执行图 xff1a 按照我们想让它执行的顺序执行 xff0c 结果应该是3 但在多
  • 2013年十佳优秀主席将获得传智播客.NET学院培训名额

    2013年CSDN高校俱乐部十佳优秀主席将会免费获得价值9580元的传智播客 NET学院免费培训名额 培训时间为2015年之前有效 优秀主席评选截止日期为10月底 截止日期之前请提交你的评选内容 评选内容是俱乐部介绍 自我介绍和俱乐部活动介
  • MySQL各数据类型的特点

    MySQL各数据类型的特点 常用的整数类型 常见误区 int n 是设置数据最大的显示宽度 xff0c 所占的存储空间不会改变 常用的浮点类型 123456789 987654321 61 decimal 18 9 占用9个字节 涉及财务等
  • Redis持久化——RDB、AOF

    Redis持久化 RDB AOF 什么是持久化 redis所有数据都保存在内存中 xff0c 对数据的更新异步保存到磁盘上 在Redis中持久化的方式有两种 xff0c 一种是快照持久化 xff0c 一种是AOF持久化 xff0c 各有各的
  • Redis主从复制—看完这篇你就懂了

    Redis主从复制 主从复制 xff0c 是指将一台Redis服务器的数据 xff0c 复制到其他的Redis服务器 前者称为主节点 master leader xff0c 后者称为从节点 slave follower xff1b 数据的复
  • 轻松搞定单例模式以及线程安全等问题

    单例模式 单例模式 xff08 Singleton Pattern xff09 是 Java 中最简单的设计模式之一 这种类型的设计模式属于创建型模式 xff0c 它提供了一种创建对象的最佳方式 这种模式涉及到一个单一的类 xff0c 该类
  • 设计模式之原型模式

    原型模式 定义 xff1a 指原型实例指定创建对象的种类 xff0c 并且通过拷贝这些原型创建新的对象 不需要知道任何创建的细节 xff0c 不需要调用构造函数类型 xff1a 创建型 适用的场景 类初始化消耗较多资源 xff08 比较重的