原型模式:
- 有时候,我们需要一个实例,但是创建这个实例的过程比较复杂,比如构造函数非常的复杂,执行这个构造函数时会消耗较长的时间,但另外一方面,这个构造函数中的一些信息又没有什么变化(也就是说创建第一个实例时初始化信息是这样的,创建第二个实例时初始化信息还是还是这样的),那么直接使用new再创建这样一个实例就显得太昂贵了,此时可以使用克隆,也就是复制,就是通过复制现在已经有了的实例来创建新的实例。
深拷贝与浅拷贝
- object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝(也称为影子拷贝)。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。
- 对象类的克隆方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝(也称为影子拷贝)。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝.上面clone简历的操作中发现,clone的所有的简历共享同一个Address,这就是因为只是进行了浅拷贝,Address是引用数据类型,没有进行复制。如果要同时复制,需要使用深拷贝实现。上面克隆简历的操作中发现,克隆的所有的简历共享同一个地址,这就是因为只是进行了浅拷贝,Address是引用数据类型,没有进行复制。如果要同时复制,需要使用深拷贝实现.
优点:
- 使用原型模式创建对象比直接new一个对象在性能上要好的多(一般情况下),因为object类的clone方法是一个本地native方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
- 简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
- 底层直接复制,不通过构造方法,也不受权限修饰符的影响。
缺点:
- 需要为每一个类配置一个克隆方法,而且该克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。
- 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重签到引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。
适用情况:
- 要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。
- 需要注意的是∶我们可以利用clone方法来实现对象之间的复制,但对于比较复杂的对象(比如对象中包含其他对象,其他对象又包含别的对象…)这样我们必须进行层层深度clone,每个对象需要实现cloneable接口,比较麻烦,此时采用序列化也是一个不错的万法(可以先使用objectOutputStream的writeObject 实现序列化到一个字节数组,不用序列化到硬盘或者网络,再使用objectInputStream的readObject反序列化就生成一个一模一样的对象,不管多么复杂的结构)。
public class Resume implements Cloneable{
private String name;
private String sex;
private int age;
private Address address;
@Override
public Resume clone() throws CloneNotSupportedException {
Resume resume =(Resume)super.clone();
return (Resume)super.clone();
}
public Resume() {
}
@Override
public String toString() {
return "Resume{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", address=" + address +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Resume(String name, String sex, int age, Address address) {
this.name = name;
this.sex = sex;
this.age = age;
this.address = address;
}
}
public class Address {
private String city;
private String disstriot;
private String street;
public Address() {
}
@Override
public String toString() {
return "Address{" +
"city='" + city + '\'' +
", disstriot='" + disstriot + '\'' +
", street='" + street + '\'' +
'}';
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDisstriot() {
return disstriot;
}
public void setDisstriot(String disstriot) {
this.disstriot = disstriot;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public Address(String city, String disstriot, String street) {
this.city = city;
this.disstriot = disstriot;
this.street = street;
}
}
public class Tset {
public static void main(String[] args) throws CloneNotSupportedException {
Address address=new Address("云南省","昭通","巧巧街道");
Resume resume1 = new Resume("巧巧","女",23,address);
address.setCity("大理");
System.out.println(resume1);
Resume resume2 = resume1.clone();
System.out.println(resume2);
Resume resume3 = resume1.clone();
System.out.println(resume3);
}
}
以上操作被定义为:浅拷贝 ;打开注释就是深拷贝大家自己动手实现一遍即可掌握
技术的升级迭代只是为了淘汰那些不学习的人!!!