-
Specify the kinds of objects to create using a prototypical instance,and create new objects bycopying this prototype.(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)简单说明就是不通过new关键字产生对象,而是通过对象复制来实现就叫做原型模式。
原型模式的核心就是一个clone()方法,通过该方法进行对象拷贝,java底层提供了一个Cloneable接口来标示这个对象是可拷贝的,这个借口只是一个标记作用,在JVM中有这个标记的对象才能被拷贝。
原型模式注意事项
1.构造函数不会被执行。我们举例说明为什么不会执行构造函数。
/**
* @author shuliangzhao
* @Title: Car
* @ProjectName design-parent
* @Description: TODO
* @date 2019/5/31 22:57
*/
public class Car implements Cloneable{
public Car() {
System.out.println("我是一辆跑车...");
}
@Override
public Car clone() {
Car car = null;
try{
car = (Car)super.clone();
}catch (Exception e) {
e.printStackTrace();
}
return car;
}
}
客户端
/**
* @author shuliangzhao
* @Title: CarClient
* @ProjectName design-parent
* @Description: TODO
* @date 2019/5/31 22:59
*/
public class CarClient {
public static void main(String[] args) {
Car car = new Car();
Car clone = car.clone();
}
}
运行结果
从运行结果我们可以看出只打印一句话 说明构造函数没执行。Object类的clone方法的原理是从内存中(具体地说就是堆内存)以二进制流的方式进行拷贝,重新分配一个内存块,那构造函数没有被执行也是非常正常的了。
浅拷贝和深拷贝
浅拷贝例子
/**
* 浅拷贝
* @author shuliangzhao
* @Title: Thing
* @ProjectName design-parent
* @Description: TODO
* @date 2019/5/31 22:26
*/
public class ShallowThing implements Cloneable {
private List<String> list = new ArrayList<String>();
@Override
public ShallowThing clone() {
ShallowThing thing = null;
try {
thing = (ShallowThing) super.clone();
}catch (Exception e) {
e.printStackTrace();
}
return thing;
}
public void setList(String s) {
this.list.add(s);
}
public List<String> getList() {
return this.list;
}
}
客户端Client
/**
* @author shuliangzhao
* @Title: Client
* @ProjectName design-parent
* @Description: TODO
* @date 2019/5/31 22:30
*/
public class Client {
public static void main(String[] args) {
//浅拷贝
ShallowThing thing = new ShallowThing();
thing.setList("张三");
ShallowThing clone = thing.clone();
clone.setList("李四");
System.out.println(thing.getList());
//深拷贝
/* DeepThing deepThing = new DeepThing();
deepThing.setList("王五");
DeepThing clone1 = deepThing.clone();
clone1.setList("张柳");
System.out.println(deepThing.getList());
System.out.println(clone1.getList());*/
}
}
执行结果
执行结果是两个,因为java做了一个偷懒的动作,clone方法只拷贝对象,对象内的数组和引用对象等都不拷贝,这就是浅拷贝。两个对象共享一个变量是一种非常不安全的方式。但是String字符串比较特殊,通过字符串池(stringpool)在需要的时候才在内存中创建新的字符串。所以使用String时候可以当做基本类型就可以。
深拷贝例子
/**
* @author shuliangzhao
* @Title: DeepThing
* @ProjectName design-parent
* @Description: TODO
* @date 2019/5/31 22:32
*/
public class DeepThing implements Cloneable{
private ArrayList<String> list = new ArrayList<String>();
@Override
public DeepThing clone() {
DeepThing thing = null;
try {
thing = (DeepThing) super.clone();
this.list = (ArrayList<String>)this.list.clone();
}catch (Exception e) {
e.printStackTrace();
}
return thing;
}
public void setList(String s) {
this.list.add(s);
}
public List<String> getList() {
return this.list;
}
}
客户端Client
/**
* @author shuliangzhao
* @Title: Client
* @ProjectName design-parent
* @Description: TODO
* @date 2019/5/31 22:30
*/
public class Client {
public static void main(String[] args) {
//浅拷贝
/*ShallowThing thing = new ShallowThing();
thing.setList("张三");
ShallowThing clone = thing.clone();
clone.setList("李四");
System.out.println(thing.getList());*/
//深拷贝
DeepThing deepThing = new DeepThing();
deepThing.setList("王五");
DeepThing clone1 = deepThing.clone();
clone1.setList("张柳");
System.out.println(deepThing.getList());
System.out.println(clone1.getList());
}
}
执行结果
从上图可以看出第一个执行结果只有一个值。这就是深拷贝。
原型模式优点
1.性能好,因为是二进制拷贝,比new一个对象性能好。
2.不依赖构造函数