原型模式

原型模式

原型模式是指用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。适合原型模式的情景如下:程序需要从一个对象出发,得到若干个和其状态相同,并可独立变化其状态的对象时;对象创建需要独立于它的构造方法和表示时;以原型为基础,克隆新的对象,并完善对象实例变量时。

潜复制

如果原型对象的成员变量是值类型,则将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说,原型对象和克隆对象的成员变量指向相同的内存地址。简单来说潜克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量没有复制。

public class Address{

    String pro;
    String city;
    String zip;

    public Address(String p, String c, String z){
        pro = p;city=c;zip =z;
    }

    public String getPro() {
        return pro;
    }

    public void setPro(String pro) {
        this.pro = pro;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getZip() {
        return zip;
    }

    public void setZip(String zip) {
        this.zip = zip;
    }
}

public class Student {

    String name;
    int age;
    Address add;

    public Student(String name, int age, Address add) {
        this.name = name;
        this.age = age;
        this.add = add;
    }
    // 利用构造潜复制
    public Student(Student s){
        this.name = s.getName();
        this.age = s.getAge();
        this.add = s.getAdd();
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Address getAdd() {
        return add;
    }

    public void setAdd(Address add) {
        this.add = add;
    }
}

测试方法: 发现student 是两个地址,而add地址值并未改变。

@Test
    public void testbasClone(){
        Address adr = new Address("tianjin","tj","hedong");
        Student st1 = new Student("zhang",20,adr);
        Student st2 = new Student(st1);

        System.out.println(st1);
        System.out.println(st2);
        System.out.println(st1.getAdd());
        System.out.println(st2.getAdd());
    }
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Student@157ec23b
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Student@44d64d4e
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Address@1dd74143
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Address@1dd74143

深复制

在深复制中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象。深克隆将原型对象的所有对象引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也复制。

address中增加构造方法:

    public Address(Address address){
        this.pro = address.getPro();
        this.city = address.getCity();
        this.zip = address.getZip();
    }

student中修改构造方法:

   public Student(Student s){
        this.name = s.getName();
        this.age = s.getAge();
        this.add = new Address(s.getAdd());
    }

此时运行测试方法结果如下:(地址全部改变)

com.example.bootapitest.bookschema.fiveprototype.bacecopy.Student@157ec23b
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Student@44d64d4e
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Address@1dd74143
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Address@526a9908

Cloneable 接口实现深浅复制

潜复制

实现cloneable

public class Student implements Cloneable{

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

}
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Student@633fd91
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Student@355c94be
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Address@97a145b
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Address@97a145b

深复制

如果用clone深复制需要引用类型也继承cloneable接口:

public class Address implements Cloneable{

   @Override
    public Object clone() throws CloneNotSupportedException {
        Address s = (Address) super.clone();
        return s;
    }
}

student中需要修改clone

    @Override
    public Object clone() throws CloneNotSupportedException {
        Student student = (Student) super.clone();
        student.setAdd((Address) add.clone());
        return student;
    }

测试结果

com.example.bootapitest.bookschema.fiveprototype.bacecopy.Student@60d6fdd4
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Student@66f28a1f
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Address@60a19573
com.example.bootapitest.bookschema.fiveprototype.bacecopy.Address@44a085e5

利用Serializable序列化接口方法

学生类实现两个接口:
public class Student implements Cloneable,Serializable

地址类实现:public class Address implements Serializable

 @Override
    public Object clone() throws CloneNotSupportedException {
       Object object = null;
       try {
           ByteArrayOutputStream bos = new ByteArrayOutputStream();
           ObjectOutputStream oos = new ObjectOutputStream(bos);
           oos.writeObject(this);
           // 从流中读取
           ByteArrayInputStream ios = new ByteArrayInputStream(bos.toByteArray());
           ObjectInputStream ois = new ObjectInputStream(ios);
           object = ois.readObject();
       }catch (Exception e){e.printStackTrace();}
       return object;
    }

运行结果:

com.example.bootapitest.bookschema.fiveprototype.testSerializable.Student@df921b1
com.example.bootapitest.bookschema.fiveprototype.testSerializable.Student@1db7157f
com.example.bootapitest.bookschema.fiveprototype.testSerializable.Address@4db60246
com.example.bootapitest.bookschema.fiveprototype.testSerializable.Address@75e27856
阅读更多
换一批

没有更多推荐了,返回首页