0%

原型模式

原型模式即对对象进行拷贝,快速在Java内存堆中创建一个新的对象,按照对象的引用类型是否一起拷贝复制分为深拷贝和浅拷贝,深拷贝会把对象的引用类型也在内存中创建出一个新的对象,而浅拷贝不会创建新的引用类型对象,因此浅拷贝出的新对象的引用对象指向还是原先的同一引用对象;

在Java中Object类包含 protected Object clone();方法,由于Object是所有类的超父类,所以之类首先需要复写clone方法,并将访问修饰修改为public,除此之外Jdk会调用clone方法的类做检查,如果没有实现Cloneable接口去调用clone方法,会抛出CloneNotSupportedException异常,因此原型类还需要实现该接口;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class People implements Cloneable, Serializable {
private String name;
private int age;
private Job job;

//getter, setter...

@Override
public String toString() {
return "People{" + "name='" + name + '\'' + ", age=" + age + ", job=" + job + '}';
}

@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}

public static class Job implements Serializable{
private String place;

//getter, setter...

@Override
public String toString() {
return "Job{" + "place='" + place + '\'' + '}';
}
}
}

对People进行浅拷贝,得到新的对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test Main {
public static void main(String[] args) {
People people = new People("tom").setAge(30).setJob(new People.Job().setPlace("A"));
People people1 = (People) people.clone();

//false
System.out.println(people1 == people);
//People{name='tom', age=30, job=Man{place='A'}}
System.out.println(people);

people1.setName("jerry");
people1.getJob().setPlace("B");

//People{name='tom', age=30, job=Man{place='B'}}
System.out.println(people);
//People{name='jerry', age=30, job=Man{place='B'}}
System.out.println(people1);
}
}

可以看到,值类型拷贝成功,单引用类型拷贝的还是原先的引用,如果需要对Job也进行拷贝,这时有两种做法:

  1. 内层级类实现clone方法,在最外层把内层类拷贝后重新赋值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //People clone()
    @Override
    public Object clone() {
    try {
    People people = (People) super.clone();
    people.setJob((Job) people.getJob().clone());
    return people;
    } catch (CloneNotSupportedException e) {
    return null;
    }
    }

    //Job clone()
    @Override
    protected Object clone() throws CloneNotSupportedException {
    return super.clone();
    }
  2. 把类和引用类都实现序列化接口Serializable,利用序列化进行深拷贝
    1
    2
    //借助序列化进行深度=拷贝
    People people1 = SerializationUtils.clone(people);