//参考文档
https://blog.csdn.net/qq_40709468/article/details/82316418
原型(Prototype)模式的定义:用一个已经创建的实例作为原型,
通过复制该原型对象来创建一个和原型相同或相似的新对象。
使用场景:
1创建对象成本比较大,比如初始化要很长时间的,占用太多CPU的,
新对象可以通过复制已有的对象获得的,如果是相似的对象,则可以对其成员变量稍作修改。
2系统要保存对象状态的,而对象的状态改变很小。
3需要避免使用分层次的工厂类来创建分层次的对象,并且类的对象就只用一个或很少的组合状态!
原型模式的优缺点
原型模式作为一种快速创建大量相同或相似的对象方式,在软件开发种的应用较为广泛,很多软件提供的CTRL+C和CTRL+V操作的就是原型模式的典型应用!
优点
当创建的对象实例较为复杂的时候,使用原型模式可以简化对象的创建过程!提高效率。
缺点
需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的里面,当对已有的类经行改造时需要修改源代码,违背了开闭原则。
在实现深克隆的时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用的时候,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现相对麻烦。
原型模式适用场景
在以下情况可以考虑使用。
深克隆与浅克隆
类中的字段对应对象中的属性,这些属性全为基本类型时,subject1----clone---subject2, copy(clone)之后可以保证完全独立的两份,即相对应地将对象subject1的值赋给对象subject2。这种称之为浅拷贝。
如果类对象的属性中含有引用,比如:private List<String> hobby; 则此时,原型对象和克隆对像中关于属性hobby引用只向的是同一块内存。深克隆需要解决这个问题。解决办法就是再克隆函数中,将相关引用对象重新确定。
测试demo
step1 处理原型类(违背开闭原则)。
实现 Cloneable接口,实现protected Object clone()方法,注意该方法是继承自Object。
浅拷贝
package java_basic.stu_design_mode.stu_prototype;
import lombok.Data;
//浅拷贝
import java.util.List;
@Data
public class People implements Cloneable{//虽然Cloneable 里面是空的也必须写
private String name;
private int age ;
private List<String> hobby;
public int getNumber(){
return age+1000;
}
public People(String name, int age, List<String> hobby) {
System.out.println("调用People的构造方法");
this.name = name;
this.age = age;
this.hobby = hobby;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getMessage(){
return "hello world";
}
}
换成深拷贝只需将
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
改一下就行,如下
@Override
protected Object clone() throws CloneNotSupportedException {
People people = (People)super.clone();
List<String> list = this.getHobby();
List<String> reList = new ArrayList<>();
for(int i=0;i<list.size();i++){
reList.add(list.get(i));
}
people.hobby=reList;
return people;
}
调用(浅拷贝)
package java_basic.stu_design_mode.stu_prototype;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class Main {
@Test
public void method() {
List<String> list = new ArrayList();//调用People的构造方法
list.add("fruit");
list.add("candy");
list.add("fishing");
try {
People p1 = new People("小明",999,list);
People p2 = (People)p1.clone();//此时没有调用构造函数
System.out.println("p1==p2 is "+(p1==p2));//p1==p2 is false
System.out.println("p1.getName()===>"+p1.getName());//p1.getName()===>小明
System.out.println("p2.getName()===>"+p2.getName());//p2.getName()===>小明
p2.setName("小刚");
System.out.println("p1.getName()===>"+p1.getName());//p1.getName()===>小明
System.out.println("p2.getName()===>"+p2.getName());//p2.getName()===>小刚
//true 说明引用类型指向的内存是同一块内存,这就属于浅拷贝
System.out.println("p1.getHobby()==p2.getHobby() "+(p1.getHobby()==p2.getHobby()));//p1.getHobby()==p2.getHobby() true
System.out.println("p1.getHobby().get(0)===>"+p1.getHobby().get(0));//p1.getHobby().get(0)===>fruit
System.out.println("p2.getHobby().get(0)===>"+p2.getHobby().get(0));//p2.getHobby().get(0)===>fruit
p1.getHobby().set(0,"aaa");
System.out.println(p2.getHobby().get(0));//aaa
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}