原型模式-简单实现和Spring源码分析

本文深入探讨Java中的原型模式,解析其原理与应用,包括Cloneable接口的使用、深拷贝与浅拷贝的区别,以及在Spring框架中的实现。通过实例演示如何高效创建对象副本,提高性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设计模式-总览icon-default.png?t=LBL2https://mp.csdn.net/mp_blog/creation/editor/122202507    设计模式并不是Java独有的,但是Java提供了一个接口Cloneable,只要有一个类实现了该接口则可以在内存中直接拷贝对象,让原型模式的实现变的非常的简单。但是Cloneable接口是浅拷贝(这个就要去理解一下深拷贝和浅拷贝的区别了)。所以当一个对象进行clone时,如果对象中存在对象,如User对象有个属性Department dept是对象,则克隆出来的对象和源对象的dept属性指向同一内存地址,如某一对象对其进行了更改,则都进行了更改,再拷贝给其他人的也都是改变后的。由于线上环境比较复杂,所以这种一般还是建议使用深拷贝。

    使用深深拷贝有两种方式:第一就是在上面的情况,对象内部的所有对象都实现Cloneable接口,即Department类也实现Cloneable接口。第二就是可以使用序列化方式(当然这不是很建议,可以查看之前写的序列化相关的博客Java序列化)。

    应用场景:

    1、因为Cloneable的clone()方法在内存中进行实现的,所以效率非常高。如果有大量差不多的对象需要创建并且大多数字段都差不多,每次去进行new则会比较影响性能。

    2、被拷贝之后不能判断数据会怎么进行修改,则需要对源模板对象进行保护。比如Spring 中或者原型对象时。但是个人觉得这种场景不会很多,微服务之后的每个jvm内部,对象做了什么还是比较清楚的。跨进程的调用进行了序列化和反序列化也不用考虑太多。

一、原型模式实现

    自己模拟一个场景,需要初始化很多的对象,该对象内部有很多字段是值相同的。

@Data
public class User implements Cloneable {

    private Long id;

    private String name;

    private Department department;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", department=" + "{deptId='" + department.getId()
                + "',deptName='" + department.getName() + "'}" +
                '}';
    }
}
@Data
public class Department implements Cloneable {

    private Long id;

    private String name;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

个人觉得原型模式可能经常和简单工厂模式一起进行使用。

public class UserInitFactory {

    /**
     *  为了最后方便大于原型的对象数据,修改为public方法
     */
    public static final User user = new User();

    static {
        Department department = new Department();
        department.setId(123L);
        department.setName("研发部");
        user.setId(1L);
        user.setName("kevin");
        user.setDepartment(department);
    }

    /**
     *  个人觉得原型模式可能经常牵扯 简单工厂模式
     * @return 用户
     */
    public static User getUser() {
        try {
            return (User)user.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

测试类:

public class PrototypeTest {

    public static void main(String[] args) {
        for (int i = 0; i < 1000; i++) {
            User user = UserInitFactory.getUser();
            user.setId(i + 1L);
            user.setName("名称" + i);
            System.out.println("生产出来第" + i + "个模板的用户:" + user);
        }
        System.out.println("原模板数据为:" + UserInitFactory.user.toString());
    }
}

输出:

。。。。。。

生产出来第998个模板的用户:User{id=999, name='名称998', department={deptId='123',deptName='研发部'}}
生产出来第999个模板的用户:User{id=1000, name='名称999', department={deptId='123',deptName='研发部'}}
原模板数据为:User{id=1, name='kevin', department={deptId='123',deptName='研发部'}}

二、Spring中的原型模式分析

。。。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值