原型设计模式
今天我们来聊一下原型设计模式,它主要的作用就是克隆对象,省去创建对象和填充属性的过程。
对前端JS有了解的兄弟,应该对这个设计模式很熟悉了,前端的各种框架通过对一些内置对象的原型进行修改,来实现不同的效果。在Java中也类似。
在Java中它做的事情就是:克隆对象,对应的API就是Object中的clone()方法。
它在Java中存在两个分类
- 深克隆。会将对象内部的引用类型也克隆一份。
- 浅克隆。不会克隆对象内部的引用类型,克隆出来的对象的引用类型变量相同。
下面我们来看一下具体的场景实现:
我们需要对一个对象进行克隆,这个对象内部包含一个引用类型的变量。我们看一下它的类图
浅克隆:
深克隆:
我们来看以下具体的代码实现
**浅克隆:**此时克隆出来的account对象是同一个对象。
public class PrototypeDesgin {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.account = new Account();
Person person1 = (Person)person.clone();
System.out.println(person.account == person1.account);//true
}
}
class Account{
int money ;
}
class Person implements Cloneable{
String name ;
int age ;
Account account ;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
**深克隆:**此时克隆出来的account不是同一个对象。
public class PrototypeDesgin {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.account = new Account();
Person person1 = (Person)person.clone();
System.out.println(person.account == person1.account);//false
}
}
class Account implements Cloneable{
int money ;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
String name ;
int age ;
Account account ;
@Override
protected Object clone() throws CloneNotSupportedException {
Person clone = (Person)super.clone();
clone.account = (Account)account.clone();
return clone ;
}
}
我们可以看到对于引用类型而言,浅克隆不会进行克隆,只有通过深克隆才能对引用类型进行克隆。这个时候有兄弟要问了,对于字符串会如何呢?
其实这个问题很好解释,字符串是在常量池中的,刚刚克隆以后,两个字符串变量的引用的确相同,但是当字符串改变以后就会重新指向一个新的字符串,所以对于字符串而言它一直都是深克隆。
还有一个问题,如果是通过new创建的字符串对象呢?我们都知道,通过new创建的字符串对象是创建了两个对象,那么当进行克隆的时候,其克隆的对象都是一个对象,而当我们对对象进行修改的时候,这个对象字符串本身也会发生变化,即它的克隆逻辑和字符串相同。
本文使用 mdnice 排版