原型模式就是单例模式的反面,单例模式就是永远只有一个对象,原型模式是两个不同的对象,业务场景有:数据转换的时候 用BeanUtils.copy (对vo bo po)
原型模式分为浅克隆和深克隆
浅克隆
浅克隆1
public class Student implements Cloneable {
private int age;
private String name;
public Student(){}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
Student student1 = new Student(20, "张三");
Student student2 = (Student) student1.clone();
student2.setAge(22);// 注意修改student2的age值 但是没有影响 student1的值
student2.setName("李四");// 注意修改student2的nage值 但是没有影响 student1的值
System.out.println(student1 == student2);//值不一样,代表不是单例模式那样是同一个对象
System.out.println("student1:" + student1.getName() + "-->"+ student1.getAge());
System.out.println("student2:" + student2.getName() + "-->"+ student2.getAge());
}
}
运行结果
false
student1:张三-->20
student2:李四-->22
浅克隆2
class Teacher implements Cloneable {
private String name;
private Student student;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
@Override
public String toString() {
return "Teacher [name=" + name + ", student=" + student + "]";
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
Student s1 = new Student();
s1.setAge(20);
s1.setName("张三");
Teacher teacher1 = new Teacher();
teacher1.setName("小赵老师");
teacher1.setStudent(s1);
//为什么会出现以下结果, Teacher中的clone方法
Teacher teacher2 = (Teacher)teacher1.clone();
teacher2.setName("小李老师");
Student s2 = teacher2.getStudent();
s2.setName("李四");
s2.setAge(30);
System.out.println(teacher1 == teacher2);//值不一样,代表不是单例模式那样是同一个对象
System.out.println("teacher1:"+teacher1);
System.out.println("teacher2:"+teacher2);
}
}
运行结果:
false
teacher1:Teacher [name=小赵老师, student=Student [age=30, name=李四]]
teacher2:Teacher [name=小李老师, student=Student [age=30, name=李四]]
可以看出改了teacher2 的name值,对teacher1不影响,但是改了teacher2的Student 中的值,连teacher1的Student 中的值也跟着改变了,所以说浅克隆有个问题就是对象里面的对象是直接copy引用的
注:用浅克隆的方式copy一个新对象,比new对象快了很多倍,但是如果一个对象里面就几个参数,没有复杂耗时操作,直接new对象可能比浅克隆更快,可以自己在构造方法写个sleep(2000) ,然后循环生成很多对象,用浅克隆和直接newduix两种方式分别打印耗时即可
深克隆
@Override
public Object clone() throws CloneNotSupportedException {
Teacher teacher = (Teacher)super.clone();
teacher.setStudent((Student)teacher.getStudent().clone());
return teacher;
}
改下clone方法,重新运行结果:
false
teacher1:Teacher [name=小赵老师, student=Student [age=20, name=张三]]
teacher2:Teacher [name=小李老师, student=Student [age=30, name=李四]]
深克隆,就是把对象的对象再次调用clone即可,当然可以用序列化,反序列化的方法解决
@Override
public Object clone(){
try {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(this);
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in =new ObjectInputStream(byteIn);
return in.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}