设计模式系列--23种常见设计模式之原型模式(12)

原型模式

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,让创建的新对象保持和原有对象相同的内容

原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要指定任何创建的细节,就像克隆。

比如如下代码实例:

公共代码Address类:

package cn.pers.sample.prototype;

import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;

/**
 * @author WeiSong <br>
 * @since 0.0.1
 * 2020/11/20 17:49
 */
@Setter
@Getter
public class Address implements Cloneable, Serializable {
    private String prov;
    private String city;
    private String district;

    @Override
    public String toString() {
        return "Address{" +
                "prov='" + prov + '\'' +
                ", city='" + city + '\'' +
                ", district='" + district + '\'' +
                '}';
    }

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

实例1:

创建user对象,内部包含 基本类型 和 引用类型,直接使用原生的clone()方法,注意需要实现 Cloneable,分别打印查看结果比较。

package cn.pers.sample.prototype;

import lombok.Getter;
import lombok.Setter;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 这里注意实现Cloneable接口很重要,如果没有实现,在进行clone方法调用时会抛出CloneNotSupportedException
 *
 * @author WeiSong <br>
 * @since 0.0.1
 * 2020/11/20 17:32
 */
@Getter
@Setter
public class User implements Cloneable, Serializable {

    private int id;
    private String name;
    private Integer age;
    private String detail;
    private Address address;
    private Map<String, String> map;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", detail='" + detail + '\'' +
                ", address=" + address.toString() +
                ", map=" + map.keySet().toString() +
                '}';
    }

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

    public static void main(String[] args) throws CloneNotSupportedException {
        /** 初始化一个对象 */
        User user = new User();
        user.setId(1);
        user.setName("Mars");
        user.setAge(12);
        user.setDetail("我爱学java,骗人的。");
        Address address = new Address();
        address.setProv("SH");
        address.setCity("SH");
        address.setDistrict("SH");
        user.setAddress(address);
        Map map = new HashMap();
        map.put("aaa", "asdas");
        map.put("bbb", "anjksna");
        user.setMap(map);

        System.out.println(user.toString());
        System.out.println("原生对象打印结束");

        /** 第一轮操作 直接调用clone方法,比较复制后的对象和原有对象 结果 */
        User user1 = (User) user.clone();
        System.out.println(user1.toString());

        System.out.println(user == user1);
        System.out.println(user.equals(user1));

        System.out.println(user.getDetail() == user1.getDetail());
        System.out.println(user.getDetail().equals(user1.getDetail()));

        System.out.println(user.getAge() == user1.getAge());
        System.out.println(user.getAge().equals(user1.getAge()));

        System.out.println(user.getAddress() == user1.getAddress());
        System.out.println(user.getAddress().equals(user1.getAddress()));

        System.out.println(user.getMap() == user1.getMap());
        System.out.println(user.getMap().equals(user1.getMap()));

        System.out.println("第一轮结束。。。。。。。。");


        /** 第二轮操作 修改后,比较复制后的对象和原有对象 结果 */
        user.setDetail("我变了");

        System.out.println(user.getDetail());
        System.out.println(user1.getDetail());

        user.getAddress().setProv("LLLL");
        System.out.println(user1.getAddress().toString());

        Address address1 = new Address();
        address1.setProv("BJ");
        address1.setCity("BJ");
        address1.setDistrict("BJ");
        user.setAddress(address1);

        System.out.println(user1.getAddress().toString());


    }
}

实例2:

创建user对象,内部包含 基本类型 和 引用类型,修改clone()方法,使用深克隆,注意需要实现序列化,分别打印查看结果比较。

package cn.pers.sample.prototype;

import lombok.Getter;
import lombok.Setter;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 这里注意实现Cloneable接口很重要,如果没有实现,在进行clone方法调用时会抛出CloneNotSupportedException
 *
 * @author WeiSong <br>
 * @since 0.0.1
 * 2020/11/20 17:32
 */
@Getter
@Setter
public class User implements Cloneable, Serializable {

    private int id;
    private String name;
    private Integer age;
    private String detail;
    private Address address;
    private Map<String, String> map;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", detail='" + detail + '\'' +
                ", address=" + address.toString() +
                ", map=" + map.keySet().toString() +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //return super.clone();
        //将对象写入流中

        ByteArrayOutputStream bao = new ByteArrayOutputStream();

        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(bao);
            oos.writeObject(this);


            //将对象从流中取出

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

            ObjectInputStream ois = new ObjectInputStream(bis);

            return ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    public static void main(String[] args) throws CloneNotSupportedException {
        /** 初始化一个对象 */
        User user = new User();
        user.setId(1);
        user.setName("Mars");
        user.setAge(12);
        user.setDetail("我爱学java,骗人的。");
        Address address = new Address();
        address.setProv("SH");
        address.setCity("SH");
        address.setDistrict("SH");
        user.setAddress(address);
        Map map = new HashMap();
        map.put("aaa", "asdas");
        map.put("bbb", "anjksna");
        user.setMap(map);

        System.out.println(user.toString());
        System.out.println("原生对象打印结束");

        /** 第一轮操作 直接调用clone方法,比较复制后的对象和原有对象 结果 */
        User user1 = (User) user.clone();
        System.out.println(user1.toString());

        System.out.println(user == user1);
        System.out.println(user.equals(user1));

        System.out.println(user.getDetail() == user1.getDetail());
        System.out.println(user.getDetail().equals(user1.getDetail()));

        System.out.println(user.getAge() == user1.getAge());
        System.out.println(user.getAge().equals(user1.getAge()));

        System.out.println(user.getAddress() == user1.getAddress());
        System.out.println(user.getAddress().equals(user1.getAddress()));

        System.out.println(user.getMap() == user1.getMap());
        System.out.println(user.getMap().equals(user1.getMap()));

        System.out.println("第一轮结束。。。。。。。。");


        /** 第二轮操作 修改后,比较复制后的对象和原有对象 结果 */
        user.setDetail("我变了");

        System.out.println(user.getDetail());
        System.out.println(user1.getDetail());

        user.getAddress().setProv("LLLL");
        System.out.println(user1.getAddress().toString());

        Address address1 = new Address();
        address1.setProv("BJ");
        address1.setCity("BJ");
        address1.setDistrict("BJ");
        user.setAddress(address1);

        System.out.println(user1.getAddress().toString());


    }
}

输出打印结果:

编者按:综上,原型模式的使用中主要要注意深浅拷贝问题,避免对象修改后相互影响。

猜你喜欢

转载自blog.csdn.net/weisong530624687/article/details/110871773