原型模式

原型模式就是单例模式的反面,单例模式就是永远只有一个对象,原型模式是两个不同的对象,业务场景有:数据转换的时候 用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;
    }

你可能感兴趣的:(原型模式)