Bean的作用域中prototype原型模式(浅拷贝和深拷贝)

在Spring中Bean有五个作用域,其中singleton和prototype分别是单例模式和原型模式。
这里讲一下单例模式和原型模式,进行整理方便我复习。

spring中bean的创建实际就是两种:单例模式和原型模式。(原型模式需要和工厂模式搭配起来)

一、原型模式
原型模式是23种设计模式的其中一种。
 在创建对象时通过new关键字创建的对象 (类加载判断,内存分配,初始化等),在我们需要大量对象时所消耗的时长会较长影响性能,原型模式相对于通过一个个去new对象而言,消耗较低。
 原型模式我们也称为克隆模式,即一个某个对象为原型克隆出来一个一模一样的对象,该对象的属性和原型对象一模一样。而且对于原型对象没有任何影响。
原型模式的克隆方式有两种:浅克隆和深度克隆。

浅克隆:只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址。

浅克隆仅仅复制所考虑的对象,而不复制它所引用的对象。只拷贝本对象,对其对象内部所有的其他引用对象以及数组等不进行拷贝,它们还是指向原来地址。Object类提供的方法clone只是拷贝本对象 , 其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址。

深克隆:深复制把要复制的对象所引用的对象都复制了一遍。

拷贝需要实现Cloneable, Serializable两个接口,重写clone方法
//浅拷贝

Pojo类:
public class User implements Cloneable, Serializable {
    private String name;
    private Date date;
    public User() {
        super();
        // TODO Auto-generated constructor stub
    }
    public User(String name, Date date) {
        super();
        this.name = name;
        this.date = date;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
}

测试:
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        System.out.println("---初始化---");
        User user = new User();
        Date date = new Date(1231231231231l);
        user.setName("zsl");
        user.setDate(date);
        System.out.println("user name:"+user.getName());
        System.out.println("user date:"+user.getDate());
        System.out.println("user:"+user);
        System.out.println("----修改时间----");
        date.setTime(123231231231l);
        user.setDate(date);
        System.out.println("修改后user中date:"+user.getDate());
        
        System.out.println("----进行浅克隆----");
        User user1 = (User) user.clone();
        user1.setName("zsl666");
        System.out.println("user1中name:"+user1.getName());
        System.out.println("user1 date:"+user1.getDate());
        System.out.println("user1:"+user1);
    }
}

//深克隆有两种方式:
//1、基于浅拷贝,重写clone方法把对象里所引用的对象全部复制
//2、使用序列化与反序列化进行深拷贝

1、基于浅拷贝实现深拷贝
Pojo类:
public class User implements Cloneable, Serializable {
    private String name;
    private Date date;
    public User() {
        super();
        // TODO Auto-generated constructor stub
    }
    public User(String name, Date date) {
        super();
        this.name = name;
        this.date = date;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stu
        Object object = super.clone();
        User user= (User) object;
        user.date= (Date) this.date.clone();
        return object;
    }
}
测试:
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        System.out.println("---初始化---");
        User user = new User();
        Date date = new Date(1231231231231l);
        user.setName("zsl");
        user.setDate(date);
        System.out.println("user name:"+user.getName());
        System.out.println("user date:"+user.getDate());
        System.out.println("user:"+user);
        
        
        User user1 = (User) user.clone();
        
        System.out.println("----修改时间----");
        date.setTime(123231231231l);
//      user.setDate(date);
        System.out.println("修改后user中date:"+user.getDate());
        
        System.out.println("----进行深克隆----");

        user1.setName("zsl666");
        System.out.println("user1中name:"+user1.getName());
        System.out.println("user1 date:"+user1.getDate());
        System.out.println("user1:"+user1);
    }
}
2、使用序列化和反序列化进行深拷贝
Pojo类:
package com.zsl.pojo;

import java.io.Serializable;
import java.util.Date;

public class User implements Cloneable, Serializable {
    private String name;
    private Date date;
    
    
    public User() {
        super();
        // TODO Auto-generated constructor stub
    }


    public User(String name, Date date) {
        super();
        this.name = name;
        this.date = date;
    }


    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }


    public Date getDate() {
        return date;
    }


    public void setDate(Date date) {
        this.date = date;
    }


    @Override
    public Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
    
    
}
测试:
public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
        System.out.println("---初始化---");
        User user = new User();
        Date date = new Date(1231231231231l);
        user.setName("zsl");
        user.setDate(date);
        System.out.println("user name:"+user.getName());
        System.out.println("user date:"+user.getDate());
        System.out.println("user:"+user);
        
        //序列化:把对象转换为字节序列的过程。
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(user);
        
        byte[] bs = bos.toByteArray();
        
        //反序列化:把字节序列恢复为对象的过程。
        ByteArrayInputStream bis = new ByteArrayInputStream(bs);
        ObjectInputStream ois = new ObjectInputStream(bis);
        User user1 = (User) ois.readObject();
        
        System.out.println("----进行深克隆----");
        user1.setName("zsl666");
        System.out.println("user1中name:"+user1.getName());
        System.out.println("user1 date:"+user1.getDate());
        System.out.println("user1:"+user1);
    }
}

通过clone的方式在获取大量对象的时候性能开销基本没有什么影响,而new的方式随着实例的对象越来越多,性能会急剧下降,所以原型模式是一种比较重要的获取实例的方式。
原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。

二、单例模式
下回补上,哈哈….

猜你喜欢

转载自www.cnblogs.com/zhangsonglin/p/11123157.html