原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
如何实现:
1,实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。
2,重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。
深拷贝和浅拷贝的区别
假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
浅拷贝
场景1:Person实现了Cloneable接口并重写了clone方法,Person有三个属性,age,score和一个Location对象引用属性,首先new出一个p1对象,p2对象来自于p1对象的clone。
实现代码:
/**
* @Author huyouting
* @Date 2021/2/29 10:39
* @Description:
*/
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person();
Person p2 = (Person)p1.clone();
System.out.println(p2.age+" "+p2.score);
System.out.println(p2.loc);
System.out.println(p1.loc ==p2.loc);
p1.loc.street ="sh";
System.out.println(p2.loc);
}
}
class Person implements Cloneable{
int age = 8;
int score =100;
Location loc = new Location("bj",22);
@Override
public Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
class Location{
String street;
int roomNo;
@Override
public String toString() {
return "Location{" +
"street='" + street + '\'' +
", roomNo=" + roomNo +
'}';
}
public Location(String street, int roomNo) {
this.street = street;
this.roomNo = roomNo;
}
}
运行结果:
结果发现当改变p1对象的Location属性时,p2对象的Location也发生了改变,因为p1,p2对象的Location引用到了同一个内存地址,当内存中的属性改变时,由于p2同样引用这个属性,所有p2的Location也发生了改变,这就是浅拷贝。
思考:如果不想改变,该如何解决?
深拷贝
解决方法就是Location同样实现Cloneable接口并重写了clone方法,当Person对象进行clone时,Location同样进行clone,具体代码实现如下:
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person();
Person p2 = (Person) p1.clone();
System.out.println(p2.age + " " + p2.score);
System.out.println(p2.loc);
System.out.println(p1.loc == p2.loc);
p1.loc.street = "sh";
System.out.println(p2.loc);
}
}
class Person implements Cloneable {
int age = 8;
int score = 100;
Location loc = new Location("bj", 22);
@Override
public Object clone() throws CloneNotSupportedException {
Person p = (Person) super.clone();
p.loc = (Location) loc.clone();
return p;
}
}
class Location implements Cloneable {
String street;
int roomNo;
@Override
public String toString() {
return "Location{" +
"street='" + street + '\'' +
", roomNo=" + roomNo +
'}';
}
public Location(String street, int roomNo) {
this.street = street;
this.roomNo = roomNo;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
此时的运行结果:
当p1的Location属性发生改变时,p1的Location并没有发生改变。