原型模式(Prototype)
解释
Object.clone()就是原型模式的一个经典应用
类图
代码
public class Test {
public static void main(String[] args) throws Exception {
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);
p1.loc.street.replace("sh", "sz");
System.out.println(p2.loc.street);
}
}
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();
}
}
知识点
要重写clone方法 类必须实现Cloneable接口
Cloneable接口:标记型接口,没有方法
不实现接口,直接重写clone方法,调用时会报错。
浅克隆
-
只克隆对象
-
如果对象中存在对象,则克隆后的对象和克隆前的对象所指向的内存地址空间是相同的。修改克隆前对象的值会影响克隆后的值。
public static void main(String[] args) throws Exception { 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); } // ======== // true // shanghai 1 // true // sh 1
深克隆
-
对象中的对象也实现Cloneable接口,克隆时顺便克隆内部对象。
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(); } }
String也是引用类型,需要深拷贝吗?
- 不需要
- String是不可变的,变的时候会新建一个String对象
- new String则会变