原型模式介绍
- 这种类型的设计模式属于创建型模式,用于创建重复的对象。
- 原型模式也就是克隆模式(通俗的来说,就是我们电脑上的复制,粘贴的操作,两个文件的内容是一模一样的,但两个都是独立的文件,无不影响。)
- JAVA中就替我们实现了原型模式。(java.lang.Cloneable中的clone()方法)
- 需要实现标记性接口Cloneable,重写clone()方法
- 需要区分浅克隆和深克隆
1.浅克隆
- 想要实现一个类的克隆,就要实现Cloneable接口,重写Object的clone方法
class Person implements Cloneable{
String name;
int age;
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test001 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person("Jungwon",22);
System.out.println(person);
System.out.println(person.hashCode());
Person person1 = (Person) person.clone();
System.out.println(person1);
System.out.println(person1.hashCode());
}
}
从结果我们可以看到person1是person克隆出来的对象,两个对象属性值相同,hashcode不同。
2.深克隆
2.1 为什么需要深克隆
当我们的类里的属性不仅有基本数据类型,还有引用类型时
class Person implements Cloneable{
String name;
int age;
Location location = new Location();
}
这时我们上面的克隆方式能否也能将类里的引用类型克隆出来?
public static void main(String[] args) throws CloneNotSupportedException {//测试
Person person = new Person("Jungwon",22);
System.out.println(person.location.hashCode());
Person person1 = (Person) person.clone();
System.out.println(person1.location.hashCode());
}
结果很明显是不能的,这时我们就需要使用到深克隆了。
2.2 深克隆的代码实现
- 实现原理很简单,引用类也实现Cloneable接口,重写clone方法
- Location类实现Cloneable接口,重写clone方法.
- 改写Person类里的clone()。
class Person implements Cloneable{
String name;
int age;
Location location = new Location("changchun");
public Object clone() throws CloneNotSupportedException {
Person person = (Person)super.clone();
person.location = (Location) location.clone();
return person;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
class Location implements Cloneable{
String loc;
public Location(String loc) {
this.loc = loc;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person("Jungwon",22);
System.out.println(person.location.hashCode());
Person person1 = (Person) person.clone();
System.out.println(person1.location.hashCode());
}
这时类中的引用类型也克隆出来了。
2.3 小疑点
这时有人会问String类型不也是引用类型吗?String也要深克隆吗?
String类型不需要进行深克隆。
因为String类型直接指定常量池,所以他本来是一个共用的。
我们都知道String是一个final修饰的,是个不可变的变量。当改变String = “abc"值为"bcd"时,其实会生成一个新的String对象值为"bcd”,所以当我们修改被克隆对象值或克隆对象值,都不会影响另一个。
3.小结
原型模式中最重要的是区分浅克隆和深克隆
3.1浅克隆和深克隆的区分
-
浅克隆: 创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
-
深克隆: 创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
总之深浅克隆都会在堆中新分配一块区域,区别在于对象属性引用的对象是否需要进行克隆(递归性的)。