Java 内部自带原型模式, 因为Java的Object类支持一个方法 Object.clone() . 原型模式也叫克隆模式。
新生成的一个对象和原来的对象属性差不多一样,没必要new一个,再赋值属性值。 直接clone一个就叫原型模式。
Cloneable 这个接口叫标记性接口,因为这个接口没有要求必须要实现的方法
注意。克隆的是属性值,如果属性是个类对象,则新克隆的对象和原对象指向的是一个引用; 这叫浅克隆。
浅克隆例子:
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);
}
}
/*
Cloneable 这个接口叫标记性接口,因为这个接口没有要求必须要实现的方法
*/
class Person implements Cloneable{
//class Person { //编译都能通过
int age = 19;
int score = 100;
Location loc = new Location("bj", 22);
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Location{
String street;
int rootNo;
public Location(String street, int rootNo) {
this.street = street;
this.rootNo = rootNo;
}
@Override
public String toString() {
return "Location{" +
"street='" + street + '\'' +
", rootNo=" + rootNo +
'}';
}
}
深克隆例子: 让属性的对象类也实现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);
System.out.println(p1.loc);
}
}
/*
Cloneable 这个接口叫标记性接口,因为这个接口没有要求必须要实现的方法
*/
class Person implements Cloneable{
int age = 8;
int score = 100;
Location loc = new Location("bj", 22);
@Override
protected Object clone() throws CloneNotSupportedException {
Person p = (Person) super.clone();
p.loc = (Location) loc.clone();
return p;
}
}
class Location implements Cloneable{
String street;
int rootNo;
public Location(String street, int rootNo) {
this.street = street;
this.rootNo = rootNo;
}
@Override
public String toString() {
return "Location{" +
"street='" + street + '\'' +
", rootNo=" + rootNo +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
**
* String类型不需要进行深克隆,因为String类型直接指向一个常量池,它本来就是共用的。
*/
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(p1.loc);
System.out.println(p2.loc);
System.out.println(p1.loc == p2.loc);
p1.loc.street = "sh";
System.out.println(p1.loc);
System.out.println(p2.loc);
p1.loc.street= p1.loc.street.replace("sh", "new.......");
System.out.println(p1.loc);
System.out.println(p2.loc);
}
}
/*
Cloneable 这个接口叫标记性接口,因为这个接口没有要求必须要实现的方法
*/
class Person implements Cloneable{
int age = 8;
int score = 100;
Location loc = new Location("bj", 22);
@Override
protected Object clone() throws CloneNotSupportedException {
Person p = (Person) super.clone();
p.loc = (Location) loc.clone();
return p;
}
}
class Location implements Cloneable{
String street;
int rootNo;
public Location(String street, int rootNo) {
this.street = street;
this.rootNo = rootNo;
}
@Override
public String toString() {
return "Location{" +
"street='" + street + '\'' +
", rootNo=" + rootNo +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person();
Person p2 = (Person) p1.clone();
System.out.println(p1.loc);
System.out.println(p2.loc);
System.out.println(p1.loc == p2.loc);
StringBuilder reverse = p1.loc.street.reverse();
System.out.println(p1.loc); //p1, p2 都会逆序。因为StringBuilder都是指向同一个对象。 所以这里要把StringBuilder再深克隆一次。
System.out.println(p2.loc);
System.out.println(p1.loc == p2.loc);
}
}
/*
Cloneable 这个接口叫标记性接口,因为这个接口没有要求必须要实现的方法
*/
class Person implements Cloneable{
int age = 8;
int score = 100;
Location loc = new Location(new StringBuilder("bj"), 22);
@Override
protected Object clone() throws CloneNotSupportedException {
Person p = (Person) super.clone();
p.loc = (Location) loc.clone();
return p;
}
}
class Location implements Cloneable{
StringBuilder street;
int rootNo;
public Location(StringBuilder street, int rootNo) {
this.street = street;
this.rootNo = rootNo;
}
@Override
public String toString() {
return "Location{" +
"street='" + street + '\'' +
", rootNo=" + rootNo +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
克隆这个模式使用的很少。 序列化和克隆没半毛钱关系。序列化是序列化当前的对象。