《JAVA设计模式系列》浅谈原型模式

原型模式

原型模式(Prototype Pattern)是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节。即用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。

  • Prototype抽象原型类,声明了clone方法,它可以是接口或基类,可以不用抽象原型类。因为万物皆对象,在Java中Object类是所有类的父类,Object类中有clone方法。

  • ConcretePrototype具体原型类,实现或者重写clone方法

原型模式的克隆分为浅克隆和深克隆。

  • 浅克隆 复制的变量和原变量的值相同,复制的引用仍指向原有的对象。

  • 深克隆 复制的变量和原变量的值相同,复制的引用将指向被复制的新对象。

浅克隆

由于 Java 提供了对象的 clone 方法,所以用 Java 实现原型模式很简单。

在 java 中自定义类必须实现 Cloneable 接口,并重写 Object 类中的 clone 方法。

public class Student implements Cloneable {

    public String name;

    public int age;

    public Dog dog;

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

    public Student(String name, int age, Dog dog) {
        this.name = name;
        this.age = age;
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", dog=" + dog +
                '}';
    }
}
public class Dog {

    private String name;

    private int age;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class PrototypeTest {
    public static void main(String[] args)throws CloneNotSupportedException {
        Student stu1 = new Student("张三",18,new Dog("dog",2));
        Student stu2 = (Student)stu1.clone();
        System.out.println(stu1);//Student{name='张三', age=18, dog=Dog{name='dog', age=2}}
        System.out.println(stu2);//Student{name='张三', age=18, dog=Dog{name='dog', age=2}}
        System.out.println(stu1 == stu2); //false
        System.out.println(stu1.dog == stu2.dog); //true
    }
}

通过运行结果发现浅拷贝出来引用类型Dog为同一个对象,若一个对象修改了属性势必会影响其它拷贝对象。

如果通过重写 clone() 方法去实现深克隆十分麻烦,需要将Dog类也实现clong()方法并在Student类的clone()中调用 Dog类的clong()因此引出了另外一种方式:序列化实现深克隆。

深克隆

在Java语言里深复制一个对象,常常可以先使对象实现 Serializable 接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里,再从流里读出来,便可以重建对象。

public class Student implements Serializable {

    public String name;

    public int age;

    public Dog dog;


    protected  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);
            Student student = (Student) ois.readObject();

            return student;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            //关闭流
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                System.out.println(e2.getMessage());
            }

        }
    }

    public Student(String name, int age, Dog dog) {
        this.name = name;
        this.age = age;
        this.dog = dog;
    }

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

public class Dog implements Serializable {

    private String name;

    private int age;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

public class PrototypeTest {
    public static void main(String[] args)throws CloneNotSupportedException {
        Student stu1 = new Student("张三",18,new Dog("dog",2));
        Student stu2 = (Student)stu1.deepClone();
        System.out.println(stu1);// Student{name='张三', age=18, dog=Dog{name='dog', age=2}}
        System.out.println(stu2);//Student{name='张三', age=18, dog=Dog{name='dog', age=2}}
        System.out.println(stu1 == stu2); //false
        System.out.println(stu1.dog == stu2.dog); //false
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值