首页 > 其他分享 >原型模式

原型模式

时间:2024-01-13 10:11:24浏览次数:26  
标签:return name 对象 value 原型 模式 public HomeWork

原型模式

是利用克隆方法克隆出新的对象.

  • 定义:原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
  • 特点:不需要知道任何创建的细节,不调用构造函数
  • 适用场景:
    •   类初始化消耗较多资源
    •   new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
    •   构造函数比较复杂
    •   循环体中产生大量对象时
  • 优点:
    •   原型模式性能比直接new一个对象性能高
    •   简化创建过程
  • 缺点:
    •   必须配备克隆方法,这个模式的核心就是克隆方法,通过这个方法进行对象的拷贝
    •   对克隆复杂对象或对克隆出的对象进行复杂改造时,容易引入风险
    •   深拷贝和浅拷贝要运用得当,否则很容易引入风险

浅拷贝

拷贝对象中嵌套的对象是引用,指向同一个内存地址,而非独立内存空间。

浅拷贝得到新的对象A+,A+的内存地址是独立的,但其内部嵌套对象B却不是独立的内存,其仍然指向先前A对象中的B对象内存地址。改变A+的成员变量不会影响原有的A对象,但改变A+中的B对象成员变量却会影响原有A对象的B对象成员变量。

IMG_256

实现方法

实现Cloneable接口,重写基类Object的clone方法。

注意:

clone是一个native方法,其要比对象之间的直接引用性能要高。

native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(C/C++)实现的文件中。Java本身不能对操作系统底层进行访问和操作,但可以通过JNI接口调用其他语言来实现对底层的访问。

深拷贝

即对象完全克隆;不管A对象中包含了多少个对象,包含的对象又嵌套多少个对象,都完全将其进行复制。复制后新对象A+,不管对A+及其内部对象做了什么操作,都不会改变原有对象A。

IMG_256

实现方法

实现Serializable接口(包括嵌套对象),自定义克隆方法,利用对象的字节流进行序列化和反序列化得到新的对象。

代码

ESexType

/**
 * <p>性别枚举类</p>
 */
public enum ESexType {

    /**
     * 枚举对象
     */
    MALE("男",0),
    FEMALE("女",1);


    private final  String name ;
    private final  Integer value;

    /**
     * 枚举构造器
     * @param name 性别名称
     * @param value 性别值
     */
    ESexType(String name, Integer value){
        this.name = name;
        this.value = value;
    }

    /**
     * 通过name获取对应的枚举对象
     * @param name 类型名称
     */
    public static ESexType getEnum(String name){
        for(ESexType sexEnum : ESexType.values()){
            if(name.equals(sexEnum.getName())){
                return  sexEnum;
            }
        }
        return  null;
    }

    /**
     * 通过value获取对应的枚举对象
     * @param value 类型值
     */
    @JsonCreator
    public static ESexType getEnum(Integer value){
        for(ESexType sexEnum : ESexType.values()){
            if(value.equals(sexEnum.getValue())){
                return  sexEnum;
            }
        }
        return  null;
    }


    public String getName() {
        return name;
    }

    @JsonValue
    public Integer getValue() {
        return value;
    }
}

EWorkType

/**
 * <p>作业枚举类</p>
 */
public enum EWorkType {

    YU_WEN("语文",0),
    SHU_XUE("数学",1),
    YING_YU("英语",2),
    WU_LI("物理",3),
    HUA_XUE("化学",4),
    SHENG_WU("生物",5);

    private final  String name ;
    private final  Integer value;

    /**
     * 枚举构造器
     * @param name 作业类型名称
     * @param value 作业类型值
     */
    EWorkType(String name, Integer value){
        this.name = name;
        this.value = value;
    }


    /**
     * 通过name获取对应的枚举对象
     * @param name 类型名称
     */
    public static EWorkType getEnum(String name){
        for(EWorkType typeEnum : EWorkType.values()){
            if(name.equals(typeEnum.getName())){
                return  typeEnum;
            }
        }
        return  null;
    }

    /**
     * 通过value获取对应的枚举对象
     * @param value 类型值
     */
    @JsonCreator
    public static EWorkType getEnum(Integer value){
        for(EWorkType typeEnum : EWorkType.values()){
            if(value.equals(typeEnum.getValue())){
                return  typeEnum;
            }
        }
        return  null;
    }


    public String getName() {
        return name;
    }

    @JsonValue
    public Integer getValue() {
        return value;
    }
}

PupilStudent

/**
 * <p>小学生 == 如果要实现对象的深度拷贝,嵌套引用类型的对象类必须也实现Serializable接口</p>
 */
@Data
public class PupilStudent implements Serializable {
    
   private static final long serialVersionUID = 1L;

   /**学号*/
    private Long sNo;

    /**年级*/
    private Integer sClass;

    /**姓名*/
    private String name;

    /**年龄*/
    private Integer age;

    /**性别*/
    private ESexType sex = ESexType.MALE;
}

HomeWork

/**
 * <p>小学生的家庭作业</p>
 */
@Data
public class HomeWork implements Cloneable, Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 作业类型
     */
    private EWorkType type = EWorkType.YU_WEN;

    /**
     * 完成时间
     */
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date finishTime;

    /**
     * 作业页码数【作业量】
     */
    private Integer pages = 0;

    /**
     * 完成者
     */
    private PupilStudent pupilStudent;

    /**
     * 对象浅拷贝  == 对象中按值类型传递部分均能完美拷贝走,但是按引用类型传递部分则拷贝不走
     *
     * @return HomeWork
     * @throws CloneNotSupportedException
     */
    @Override
    public HomeWork clone() throws CloneNotSupportedException {
        return (HomeWork) super.clone();
    }

    /**
     * 深度拷贝 == 不管你对象中是值类型部分,还是引用类型部分,我全部拿走
     * 对象字节流的序列与反序列化 ==> 对象完全、深度、彻彻底底的Copy!!!
     *
     * @return HomeWork
     */
    public HomeWork deepClone() {

        // Anything 都是可以用字节流进行表示!
        HomeWork homeWork = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            // 将当前的对象写入baos【输出流 -- 字节数组】里
            oos.writeObject(this);

            // 从输出字节数组缓存区中拿到字节流
            byte[] bytes = baos.toByteArray();
            // 创建一个输入字节数组缓冲区
            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
            // 创建一个对象输入流
            ObjectInputStream ois = new ObjectInputStream(bais);
            // 下面将反序列化字节流 == 重新开辟一块空间存放反序列化后的对象
            homeWork = (HomeWork) ois.readObject();

        } catch (Exception e) {
            System.out.println(e.getClass() + ":" + e.getMessage());
        }
        return homeWork;
    }

    @Override
    public String toString() {
        return String.format("类型:%s,页数:%s,完成时间:%s," +
                        "完成者:%s,学号:%d,年级:%d,年龄:%d,性别:%s", this.type.getName()
                , this.pages, DateUtils.date2Str(this.finishTime), this.pupilStudent.getName(),
                this.pupilStudent.getsNo(), this.pupilStudent.getsClass(),
                this.pupilStudent.getAge(), this.pupilStudent.getSex().getName());
    }
}

测试

/**
 * <p>原型模式测试 == 两种方式?</p>
 */
public class PrototypeTest {
    public static void main(String[] args) throws CloneNotSupportedException{

        // 原型 == 我们创建一个已经由小学生【刘晓然】完成的作业对象
        HomeWork homeWork = new HomeWork();
        // 设置作业信息
        homeWork.setType(EWorkType.WU_LI);
        homeWork.setPages(12);
        homeWork.setFinishTime(new Date());
        // 设置小学生信息 == 刘晓然
        PupilStudent pupilStudent  = new PupilStudent();
        pupilStudent.setsNo(1001L);
        pupilStudent.setName("刘晓然");
        pupilStudent.setAge(10);
        pupilStudent.setSex(ESexType.FEMALE);
        pupilStudent.setsClass(4);
        homeWork.setPupilStudent(pupilStudent);

        // 1、原型模式第一种 == 作业对象浅拷贝测试
        HomeWork ykHomeWork = shallowCopy(homeWork);
        System.out.println("刘晓然的作业:\n"+homeWork);
        System.out.println("我的作业:\n"+ykHomeWork);

        /**
         * 以上输出结果为:
         * 刘晓然的作业:
         * 类型:物理,页数:12,完成时间:2018年11月08日 14时03分45秒,完成者:Appleyk,学号:1002,年级:4,年龄:10,性别:男
         * 我的作业:
         * 类型:物理,页数:12,完成时间:2018年11月09日 14时03分45秒,完成者:Appleyk,学号:1002,年级:4,年龄:10,性别:男
         */


        // 2、原型模式第二种 == 作业对象深拷贝测试
        System.out.println("=========================================分割线");

        /**
         * 假设有第三个同学,要抄作业,这个同学假设叫"张聪明"
         */

        HomeWork zhangHomeWork = deepCopy(ykHomeWork);
        System.out.println("Appleyk的作业:\n"+ykHomeWork);
        System.out.println("张聪明的作业:\n"+zhangHomeWork);

        /**
         * 以上输出结果为:
         * Appleyk的作业:
         * 类型:物理,页数:12,完成时间:2018年11月09日 14时16分11秒,完成者:Appleyk,学号:1002,年级:4,年龄:10,性别:男
         * 张聪明的作业:
         * 类型:物理,页数:12,完成时间:2018年11月09日 14时16分11秒,完成者:张聪明,学号:1003,年级:4,年龄:10,性别:男
         */
    }

    /**
     * 对象浅拷贝
     * @param homeWork
     * @return
     * @throws CloneNotSupportedException
     */
    public static  HomeWork shallowCopy(HomeWork homeWork) throws  CloneNotSupportedException{

        HomeWork myHomeWork = homeWork.clone();

        myHomeWork.setFinishTime(DateUtils.addDays(1));
        PupilStudent mySelf = myHomeWork.getPupilStudent();
        mySelf.setsNo(1002L);
        mySelf.setName("Appleyk");
        mySelf.setSex(ESexType.MALE);
       
        return  myHomeWork;
    }

    /**
     * 对象深度拷贝
     * @param homeWork
     * @return
     * @throws CloneNotSupportedException
     */
    public static  HomeWork deepCopy(HomeWork homeWork) throws  CloneNotSupportedException{

        HomeWork myHomeWork = homeWork.deepClone();
        myHomeWork.setFinishTime(DateUtils.addDays(1));
        PupilStudent mySelf = myHomeWork.getPupilStudent();
        mySelf.setsNo(1003L);
        mySelf.setName("张聪明");
        mySelf.setSex(ESexType.MALE);
        return  myHomeWork;
    }
}

 

标签:return,name,对象,value,原型,模式,public,HomeWork
From: https://www.cnblogs.com/wangzhilei-src/p/17962048

相关文章

  • 《PySpark大数据分析实战》-14.云服务模式Databricks介绍基本概念
    ......
  • Microsoft 365 新功能速递:数据丢失预防和信息保护策略和标签的仅查看模式
    51CTO博客链接:https://blog.51cto.com/u_13637423微软将于2024年2月推出新功能数据丢失预防和信息保护策略和标签的仅查看模式,此功能允许具有仅查看受限权限的管理员查看数据丢失预防和信息保护策略配置的详细信息,而无需编辑策略或标签配置。这将如何影响您的组织:1.     为管......
  • 详解如何在Linux(CentOS 7)命令行模式安装VMware Tools
    本例中为在Linux(以CentOS7为例)安装VMwareTools。1.首先启动CentOS7,在VMware中点击上方“VM”,点击“InstallVMwareTools...”(如已安装则显示“ReinstallVMwareTools...”)。2.在命令行输入“ls/dev”查看。3.输入“mkdir/mnt/cdrom”在/mnt目录下新建一个名为cdrom的文件夹......
  • 虚拟机网络模式之主机模式
    Host-Only模式其实就是NAT模式去除了虚拟NAT设备,然后使用VMwareNetworkAdapterVMnet1虚拟网卡连接VMnet1虚拟交换机来与虚拟机通信的,Host-Only模式将虚拟机与外网隔开,使得虚拟机成为一个独立的系统,只与主机相互通讯。其网络结构如下图所示:通过上图,我们可以发现,如果要使得虚拟机......
  • Spark on YARN的两种部署模式
     Client模式和Cluster模式最最本质的区别是:Driver程序运行在哪里。Client模式:学习测试时使用,生产不推荐(要用也可以,性能略低,稳定性略低)1.Driver运行在Client上,和集群的通信成本高2.Driver输出结果会在客户端显示Cluster模式:生产环境中使用该模式1.Driver程序在YARN......
  • 玩转Redis:哨兵模式揭秘,带你骑上“哨兵战车”
    摘要:大家好!今天我们要聊一聊Redis的哨兵模式。说到Redis,相信很多人都对它的高性能、高可靠性留下了深刻的印象。而在这众多强大的功能中,哨兵模式无疑是一个备受关注的话题!哨兵模式在Redis中的作用就像是一支战车部队,能够时刻监控并保护我们的Redis集群。当集群中的某个主节点发生......
  • Redis哨兵模式:什么是哨兵模式、哨兵模式的优缺点、哨兵模式的主观下线和客观下线、投
    什么是哨兵模式哨兵模式是Redis的高可用解决方案之一,它旨在提供自动故障转移和故障检测的功能。在传统的Redis部署中,单个Redis节点可能成为单点故障,一旦该节点宕机,整个系统将不可用。为了解决这个问题,哨兵模式引入了多个Redis节点,其中一个节点被选为主节点,其他节点作为从节点。......
  • springboot医院信息化云HIS运维平台源码 SaaS模式
    一、HIS系统HIS系统是医院最主要的系统,它主要涵盖基本流程功能,是医院系统的核心业务系统。这里的HIS指的是狭义的HIS系统,仅仅包括门诊、住院的医嘱结算相关功能的系统。一般门诊和住院是同一个系统,包括以下一些工作站:1、门诊部分挂号及预约、划价及收费、门诊处方及病历、医生排......
  • 武汉星河互娱:手游行业新趋势与盈利模式的深度解析
    随着科技的飞速发展,手游行业正以前所未有的速度在成长壮大。近日,业内专家针对手游行业的趋势和盈利模式进行了深入解析,为我们揭示了这个行业的最新动态。首先,手游行业的发展趋势正在向多元化和个性化转变。传统的游戏模式已不能满足玩家的需求,他们更加注重游戏的体验感和个性化设置......
  • 虚拟机网络模式之桥接模式
    什么是桥接模式?桥接模式就是将主机网卡与虚拟机虚拟的网卡利用虚拟网桥进行通信。在桥接的作用下,类似于把物理主机虚拟为一个交换机,所有桥接设置的虚拟机连接到这个交换机的一个接口上,物理主机也同样插在这个交换机当中,所以所有桥接下的网卡与网卡都是交换模式的,相互可以访问而不干......