设计模式 原型模式

1.设计模式背景

在某些场景下,我们需要拷贝对象,普通设计方式会直接new一个新的对象,然后setter各种属性。缺点是:这种方式太麻烦。
这时候就可以使用到原型模式,通过Object的clone方法克隆对象,或者通过流。

2.使用方法

Object对象的clone方法,能够浅拷贝对象的primitive field,使用方式如下:

public class Person implements  Cloneable{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }


}

3.如果存在引用型成员变量怎么办?

public class Person implements  Cloneable{
    private String name;
    private int age;
    private Department department;

经过测试发现,克隆对象中的department是同一个对象。

Person p1 = new Person();
        p1.setDepartment(new Department("pA"));
        Person clone = (Person)p1.clone();
        System.out.println(clone.getDepartment() == p1.getDepartment());

3.1 在覆盖的clone方法中重新设置

@Override
    protected Object clone() throws CloneNotSupportedException {
        Person res = null;
        res = (Person)super.clone();
        Department dept = (Department)this.getDepartment().clone();
        res.setDepartment(dept);
        return res;
    }

但是同样存在问题:如果引用型成员变量太多,也要一个个设置。

3.2 使用序列化

利用字节输出流,字节输入流,对象输出流,对象输入流

public Object deepClone() {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;


        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);

            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            Object o = ois.readObject();

            return o;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        finally {
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

test:

Person2 p2 = new Person2();
        p2.setDepartment(new Department("abc"));
        Person2 o = (Person2)p2.deepClone();
        System.out.println(o);
        System.out.println(p2);
        System.out.println(o.getDepartment() == p2.getDepartment());

note : 利用序列化深拷贝的成员都要实现serilizable接口

posted @ 2020-07-15 21:54  cainiao11024  阅读(110)  评论(0编辑  收藏  举报