本文讲解一下原型模式的概念并通过一个案例来进行实现。
4、原型模式
- 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
- 原型模式就是Java中的克隆技术,以某个对象为原型,复制出新的对象,新的对象具有原型对象的特点
- 原型模式的优点是效率高
- new出的对象的属性采用的是默认值,克隆出的对象的属性值和原型对象的一致,并且克隆出的对象不会影响原型对象。
原型模式的实现:
- Cloneable接口和clone方法
- 原型模式中实现最困难的地方就是内存复制操作,还好Java中提供了clone()方法替我们做了绝大部门事情
4.1、浅克隆
- 被复制的对象的所有变量与原来的变量相同,但是所有的对象的引用仍然指向原来的对象
4.2、 深克隆
- 深克隆把引用的变量指向复制过的新对象,不是原有的被引用的对象
- 基本数据类型和String能够自动实现深度克隆(值的复制)
  
4.3 代码实现
Sheep类为浅克隆,Sheep2为深克隆
public class Sheep implements Cloneable , Serializable {
    private String name;
    private Date birthday;
    public Sheep() {
    }
    public Sheep(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();//直接调用String对象的clone()方法
        return obj;
    }
}
public class Sheep2 implements Cloneable{
    private String name;
    private Date birthday;
    public Sheep2() {
    }
    public Sheep2(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();//直接调用String对象的clone()方法
        //添加如下代码,实现深克隆
       Sheep2 s= (Sheep2)obj;
       s.birthday = (Date) this.birthday.clone();
        return obj;
    }
}
客户端调用测试
/**
 * 测试浅克隆
 * @author tqq
 * @date 2021-04-26-15:45
 */
public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Date date = new Date(12423423543L);
        Sheep s1 = new Sheep("少利",date);
        Sheep s2 = (Sheep) s1.clone();
        date.setTime(1243242343243L);
        System.out.println(s1.getBirthday().getTime());//1243242343243
        System.out.println(s1.getName());
        System.out.println(s2.getBirthday().getTime());//1243242343243
        System.out.println(s2.getName());
    }
}
/**
 * 测试深克隆
 * @author tqq
 * @date 2021-04-26-15:45
 */
public class Client2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Date date = new Date(12423423543L);
        Sheep2 s1 = new Sheep2("少利",date);
        Sheep2 s2 = (Sheep2) s1.clone();
        date.setTime(1243242343243L);
        System.out.println(s1.getBirthday());//Mon May 25 17:05:43 CST 2009
        System.out.println(s1.getName());
        System.out.println(s2.getBirthday());//Mon May 25 02:57:03 CST 1970
        System.out.println(s2.getName());
    }
}
4.4、 new()方式创建对象VS克隆方式创建对象
/**
 * 测试普通new方式对象和clone方式创建对象的效率差异
 * 如果需要短时间创建大量对象并且new的过程比较耗时,则可以考虑使用原型模式
 * @author tqq
 * @date 2021-04-27-10:21
 */
public class Client4 {
    public static void main(String[] args) throws CloneNotSupportedException {
        testNew(100);//1564
        testClone(100000000);//703
    }
    public static void testNew(int size){
        long start = System.currentTimeMillis();
        for (int i = 0; i <size; i++) {
            Laptop laptop = new Laptop();
        }
        long end = System.currentTimeMillis();
        System.out.println("new的方式创建耗时:"+(end-start));
    }
    public static void testClone(int size) throws CloneNotSupportedException {
        long start = System.currentTimeMillis();
        Laptop laptop = new Laptop();
        for (int i = 0; i <size; i++) {
         Laptop l = (Laptop) laptop.clone();
        }
        long end = System.currentTimeMillis();
        System.out.println("clone的方式创建耗时:"+(end-start));
    }
}
class Laptop implements Cloneable{
    public Laptop() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();//直接调用String对象的clone()方法
        return obj;
    }
}
4.5、 应用场景
- 原型模式一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者
- Spring中的bean的创建实际就是两种:单例模式和原型模式(原型模式和工厂模式要搭建起来)



















