概念:原型模式的思想是将一个对象作为原型,对其进行复制、克隆、拷贝,产生一个和原对象类似的新对象。
使用场景:主要应用与那些创建新对象的成本过大时。
优点:简化了新对象的创建过程,提高了效率,同时原型模式提供了简化的创建结构。
实现方式:(1)创建一个原型类,实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,因为Cloneable接口是个空接口。深复制和浅复制都可以重写clone方法来实现。(2)深复制还可以通过序列化来实现。
引用复制:将原对象的引用直接赋给新对象,是同一个对象。
(1)浅复制
被复制对象的所有变量都与原来的对象得值相同,并且自身引用不同与原来,是一个全新的对象,但是对象里面的引用类型仍然指向原来的引用。简而言之,浅拷贝仅仅复制所考虑的对象,而不复制对象里面所引用的对象
实现步骤:1)实现Cloneable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常)。
2)重写clone()方法,访问修饰符设为public。方法中通过super.clone()调用Object类中的原clone方法复制对象。
浅复制只是复制了addr变量的引用,并没有真正的开辟另一块空间
(2)深复制
深复制是一个整个独立的对象复制,深复制会复制所有的属性,并复制属性指向的动态分配的内存。当对象和它所引用的对象一起复制时即发生深复制。深复制相比于浅复制速度较慢并且花销较大。
简而言之,深复制把要复制的对象和这个对象里面所引用的对象都复制了一遍。
实现方式:
(1)实现Cloneable接口,重写clone()方法。只是需要为对象里面的每一个对象都实现Cloneable接口并重写clone方法,最后在最顶层的类的重写的clone方法中调用所有的clone方法即可实现深拷贝。简单的说就是:每一层的每个对象都进行浅复制=深复制。
(2)通过对象序列化实现深复制:对象实现Serializable接口,然后序列化这个对象,最后反序列化回来,就可以得到这个新的对象。被复制的对象必须实现Serializable接口,注意:如果某个属性被transient修饰,那么该属性就无法被复制了。
// list深拷贝的方法
public static <T> List<T> deepCopy(List<T> src) throws Exception {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(src);
out.flush();
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
@SuppressWarnings("unchecked")
List<T> dest = (List<T>) in.readObject();
return dest;
}
(3)新建一个对象,然后通过set方法给新对象赋值。
(4)apache提供了这个BeanUtils来实现直接对象的拷贝,BeanUtils.copyProperties(newObj,obj);
(5)对象转JSON , 然后再把JSON转对象。