原型模式
定义:
用原型实例指定创建对象的种类, 并且通过拷贝这些原型创建新的对象。
原型模式的核心是一个clone方法, 通过该方法进行对象的拷贝, Java 提供了一个Cloneable接口来标示这个对象是可拷贝的,在JVM中具有这个标记的对象才有可能被拷贝。
比如:比如批量发送邮件,邮件模板是一样的,发送给不同的人内容不同,那么就可以把模板 clone 给不同的发送者,发送者修改一下内容模板内容,然后就发送。就是生产一个对象不是从new开始的,而是从已经存在的一个对象直接拷贝过来,然后修改修改就好了。
优点:
1、原型模式是在内存中二进制流的拷贝,要比直接new性能好很多。如果在一个循环体内创建大量对象,原型模式能体现出他的优点。
2、由于是二进制的拷贝,所有构造函数不会被执行。这也是优点,也是缺点,在实际应用中要考虑。
使用场景:
一个对象要给其它对象访问,并且其它对象可能会修改这个对象。可以考虑使用原型模式。
注意事项:
1、构造函数不会被执行
浅拷贝
Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝, 还是指向原生对象的内部元素地址, 这种拷贝就叫做浅拷贝。
注:String 是不可变的,处理机制比较特殊,通过字符串池在需要的时候才在内存中创建新的字符串。
深拷贝
对象内部的数组、引用对象等要手动拷贝。示例代码:修改上面的clone() 方法如下:
还有一点要注意的是:想要clone 的属性,不能是final的。
定义:
用原型实例指定创建对象的种类, 并且通过拷贝这些原型创建新的对象。
原型模式的核心是一个clone方法, 通过该方法进行对象的拷贝, Java 提供了一个Cloneable接口来标示这个对象是可拷贝的,在JVM中具有这个标记的对象才有可能被拷贝。
比如:比如批量发送邮件,邮件模板是一样的,发送给不同的人内容不同,那么就可以把模板 clone 给不同的发送者,发送者修改一下内容模板内容,然后就发送。就是生产一个对象不是从new开始的,而是从已经存在的一个对象直接拷贝过来,然后修改修改就好了。
优点:
1、原型模式是在内存中二进制流的拷贝,要比直接new性能好很多。如果在一个循环体内创建大量对象,原型模式能体现出他的优点。
2、由于是二进制的拷贝,所有构造函数不会被执行。这也是优点,也是缺点,在实际应用中要考虑。
使用场景:
一个对象要给其它对象访问,并且其它对象可能会修改这个对象。可以考虑使用原型模式。
注意事项:
1、构造函数不会被执行
浅拷贝
Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝, 还是指向原生对象的内部元素地址, 这种拷贝就叫做浅拷贝。
注:String 是不可变的,处理机制比较特殊,通过字符串池在需要的时候才在内存中创建新的字符串。
示例代码:
public class Prototype implements Cloneable {
private List<String> list = new ArrayList<>();
@Override
protected Object clone() throws CloneNotSupportedException {
//浅拷贝
return super.clone();
}
public void add(String str) {
list.add(str);
}
public List<String> getList() {
return list;
}
/**
* 测试代码
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception{
Prototype prototype = new Prototype();
prototype.add("A");
Prototype clone = (Prototype)prototype.clone();
clone.add("B");
//此处打出 A , B
System.out.println(prototype.getList());
//此处打出 A , B
System.out.println(clone.getList());
}
}
说明: 运行结果打印出 [A, B] prototype,clone两个对象引用的是同一样ArrayList。
深拷贝
对象内部的数组、引用对象等要手动拷贝。示例代码:修改上面的clone() 方法如下:
@Override
protected Object clone() throws CloneNotSupportedException {
//深拷贝
Prototype clone = (Prototype)super.clone();
clone.list = (ArrayList)((ArrayList)this.list).clone();
return clone;
}
修改后就正常了
还有一点要注意的是:想要clone 的属性,不能是final的。