版权声明:如果转载,请带上来源地址 https://blog.csdn.net/zhan_lang/article/details/88432194
定义:
- 原型模式(Prototype Pattern)是指用原型实例指定创建对象的 种类,并且通过拷贝这些原型创建新的对象
- 调用者不需要知道任何创建细节,不调用构造函数 属于创建性模式
那么定义有了,它的使用场景又在哪些地方呢?
使用场景:(原型模式是在内存二进制流直接拷贝)
- 类初始化消耗资源较多
- new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
- 构造函数比较复杂
- 循环体中生产大量对象时,可读性下降
说了这么多,下边给大家用代码演示一下:
首先呢 我们先创建一个类 ,里面包含年龄,姓名,以及爱好(本想用lombok代替get和set方法 但是我突然用不了)
public class LocalClone implements Cloneable {
private String name;
private int age;
/**
* 爱好
*/
private List<String> like;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getLike() {
return like;
}
public void setLike(List<String> like) {
this.like = like;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
然后我们来测试一下
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
LocalClone localClone = new LocalClone();
localClone.setAge(18);
localClone.setName("张三");
List<String> strings = new ArrayList<>();
strings.add("撸代码");
strings.add("学习");
localClone.setLike(strings);
System.out.println("原实例:爱好"+localClone.getLike());
//修改为使用clone方法
LocalClone clone = (LocalClone) localClone.clone();
clone.getLike().add("撩妹");
clone.setName("李四");
System.out.println("原实例:爱好"+localClone.getLike() + " 姓名:"+localClone.getName());
System.out.println("克隆实例:爱好"+clone.getLike()+ " 姓名:"+clone.getName());
}
}
然后我们来查看一下运行结果:
原实例:爱好[撸代码, 学习]
原实例:爱好[撸代码, 学习, 撩妹] 姓名:张三
克隆实例:爱好[撸代码, 学习, 撩妹] 姓名:李四
是不是很奇怪?为啥我修改一个对象,把另外一个对象的值都修改到了,这种方式就叫浅拷贝,这种方式要慎重使用,特别是在有类继承的时候,一定要慎重 慎重! 要把它和深拷贝分开,不然到时候就把其他对象的值改掉了
下面我们就来介绍一下什么叫浅拷贝和深拷贝
- 浅拷贝:只复制对象,对象数组,引用对象都不拷贝 对象修改会相互影响 (例如上面的例子)
- 深拷贝:完全拷贝 对象修改互不影响
那深拷贝是怎么实现的呢? 我们就来看一下 这里我们需要修改一下克隆方法,在这里先添加一个
private ArrayList arrayList; 来替换刚才的list,为什么呢?重点来了(因为arrayList有个clone方法)
@Override
protected Object clone() throws CloneNotSupportedException {
LocalClone clone = (LocalClone) super.clone();
this.arrayList = (ArrayList<String>) this.arrayList.clone();
return clone;
}
这是我们修改后的clone方法 重新执行测试类
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
LocalClone localClone = new LocalClone();
localClone.setAge(18);
localClone.setName("张三");
ArrayList<String> strings = new ArrayList<>();
strings.add("撸代码");
strings.add("学习");
localClone.setArrayList(strings);
System.out.println("原实例:爱好"+localClone.getArrayList());
//修改为使用clone方法
LocalClone clone = (LocalClone) localClone.clone();
clone.getArrayList().add("撩妹");
clone.setName("李四");
System.out.println("原实例:爱好"+localClone.getArrayList() + " 姓名:"+localClone.getName());
System.out.println("克隆实例:爱好"+clone.getArrayList()+ " 姓名:"+clone.getName());
}
}
查看输入结果:
原实例:爱好[撸代码, 学习]
原实例:爱好[撸代码, 学习] 姓名:张三
克隆实例:爱好[撸代码, 学习, 撩妹] 姓名:李四
这样我们就实现了深拷贝,对于深拷贝我们要做得就是需要手动的去修改克隆方法。(如序列化实现等)
以上就是原型模式,就是这么简单。
注意:
如果定义属性为final的 ,那么就复制不了,因为你都final,我还怎么复制。
拓展:
那么我们长接触的原型模式有哪些呢?例如:BeanUtils.copyProperties(o1,o2); JSON.parseObject(),可以去看看它们是具体实现的