原型模式

不通过new关键字来产生一个对象,而通过对象复制来生产对象的模式,原型模式的核心是clone方法,通过该方法进行对象的拷贝。

也就是先生产出一个包含大量共有信息的类对象,然后拷贝出副本修正细节信息,建立一个完整的个性对象。

定义

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

原型模式通用类图

优缺点

  • 性能好
    原型模式是内存二进制流侧拷贝,要比直接new一个对象性能好很多,特别在一个循环体内产生大量的对象时,原型模式可以更好的体现其优点。
  • 逃避构造函数的约束
    直接在内存中拷贝,构造函数不会执行。优点和缺点都是减少了约束。

使用场景

需要频繁的new一个对象,并且该对象需要繁琐的数据准备时;
一个对象要提供给其他对象访问,各个调用者可能需要修改其值时;

原型模式一般与工厂方法模式一起出现,通过clone的方法来创建对象,然后由工厂方法提供给调用者。

实现

1
2
3
4
5
6
7
8
9
10
11
12
public class PrototypeClass implements Cloneable{
@Override
public PrototypeClass clone(){
PrototypeClass p = null;
try{
p = (PrototypeClass)super.clone();
}catch(CloneNotSupportedException e){
//TODO
}
return p;
}
}

注意事项

构造函数不会被执行

Object类的clone方法原理是从内存中(堆内存)以二进制流的方式进行拷贝,重新分配一个内存快,构造函数是不会被执行的。

浅拷贝

Object类提供的方法clone只是拷贝本对象,对于其内部的数组、引用对象都不拷贝还是指向原声对象的内部元素地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class PrototypeClass implements Cloneable{
public ArrayList<String> arrayList = new ArrayList<>();

@Override
public PrototypeClass clone(){
PrototypeClass p = null;
try{
p = (PrototypeClass) super.clone();
}catch(CloneNotSupportedException e) ) {
//
}
return p;
}
}

深拷贝

深拷贝需要拷贝对象自身外,还需要拷贝对象的所有引用的对象。

通过clone方式实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class PrototypeClass implements Cloneable{
public ArrayList<String> arrayList = new ArrayList<>();

@Override
public PrototypeClass clone(){
PrototypeClass p = null;
try{
p = (PrototypeClass) super.clone();
p.arrayList = (ArrayList<String>) this.arrayList.clone();
}catch(CloneNotSupportedException e) ) {
//
}
return p;
}
}

通过序列化方式来实现,通过序列化将对象(该对象的类必须实现Serializable接口)写到一个流中,然后再从流里把对象读出来以实现深克隆。

1
2
3
4
5
6
7
8
9
public static <T extends Serializable> T clone(T t) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(t);

ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return (T)ois.readObject();
}

clone与final的冲突

当使用clone方法的时候,类的成员变量不可以增加final关键字。

拓展:
Java提高篇——对象克隆(复制)