原型模式

一、概念与通用格式

本章借鉴了《大话设计模式》之外,也借鉴了这篇博客https://www.cnblogs.com/lfxiao/p/6812835.html

原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型 创建新的对象。

这相当于是对一个对象“复制黏贴”,新的对象有自己的引用地址。

当对象创建比较复杂时,可使用原型模式。

如图:

注意:clone()里return不能return this;这样就相当于把原来的对象地址传过来,return的还是原来的对象,不是新的引用地址。

当每次new一个对象,都需要执行一次构造函数,如果构造函数执行的时间很长,那么多次操作就降低了效率。一般在初始化的信息不发生变化的情况下,克隆是很好的办法,既隐藏了对象创建的细节,又提高了性能。

二、java提供的接口

当然,像这样常用的模式,java一定给了相应的接口 Cloneable。

Java语言提供的clone():

package cn.sasa.prototypeTest;

public class ConcretePrototype2 implements Cloneable{
    private int id;
    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Object clone() {
        Object cloneObj = null;
        try {
            cloneObj = super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return cloneObj;
    }
}

 

三、浅复制与深复制

假设 我们再加一个类Pet,作为ConcretePrototype2的一个成员

package cn.sasa.prototypeTest;

import java.io.Serializable;

public class Pet implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String petName;

    public String getPetName() {
        return petName;
    }

    public void setPetName(String petName) {
        this.petName = petName;
    }

}

 

 

客户端测试:

 

我们发现,复制的新的对象和原来的是不一样的内存地址,但是对象里的引用类型的成员,clone过来的是原对象的内存地址,这就是浅复制

即浅复制是:如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用,但不复制引用的对象。

由于浅复制的引用类型成员引用的同一地址,如果更改其中一个,原模板对象也随之改变。

 深复制是和浅复制相对的,这里引用这篇博客的截图,https://www.cnblogs.com/lfxiao/p/6812835.html

 所以代码修改如下:

 

package cn.sasa.prototypeTest;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ConcretePrototype2 implements Cloneable,Serializable{

    private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    private Pet pet;
    
    public ConcretePrototype2() {
        pet = new Pet();
    }
    
    public Pet getPet() {
        return pet;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }

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

    public void SetPetName(String petName) {
        this.pet.setPetName(petName);
    }
    
    
    public Object clone() {
        Object cloneObj = null;
        try {
            cloneObj = super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return cloneObj;
    }
    
    public ConcretePrototype2 deepClone() throws IOException, ClassNotFoundException {
        //将对象写入流中

        ByteArrayOutputStream bao=new  ByteArrayOutputStream();

        ObjectOutputStream oos=new  ObjectOutputStream(bao);

        oos.writeObject(this);

       

        //将对象从流中取出

        ByteArrayInputStream bis=new  ByteArrayInputStream(bao.toByteArray());

        ObjectInputStream ois=new  ObjectInputStream(bis);

        return  (ConcretePrototype2)ois.readObject();
    }

    
}

 

测试:

 

posted @ 2019-04-10 15:18  SasaL  Views(155)  Comments(0Edit  收藏  举报