设计模式——原型模式

原型模式主要是用于拷贝对象,而生产新的对象

传统的拷贝方式:

// 创建一只叫sheep,1岁了的羊
Sheep sheep1 = new Sheep('sheep', 1);

// 拷贝这只羊
Sheep sheep2 = new Sheep(sheep1.getName(), sheep1.getAge());
Sheep sheep3 = new Sheep(sheep1.getName(), sheep1.getAge());
Sheep sheep4 = new Sheep(sheep1.getName(), sheep1.getAge());
传统方式的优缺点:

优点: 好理解,易操作

缺点: 在创建对象时需要频繁获取原对象的属性,效率低,代码冗长。

改进思路:

使用 Object类提供的clone方法,(需要实现Cloneable接口,改接口标志着该类拥有被复制的能力)
Sheep类实现
public class Sheep  implements Cloneable {
    private String name;
    private String color;
    private int age;
    private String address = "蒙古羊";
    //是对象,克隆会如何处理,默认是浅拷贝
    public  Sheep friend;

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

    public String getName() {
        return name;
    }

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

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getAge() {
        return age;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Sheep getFriend() {
        return friend;
    }

    public void setFriend(Sheep friend) {
        this.friend = friend;
    }

    //克隆该实例,使用默认的clone方法来完成,用默认的时候是前拷贝
    @Override
    protected Object clone()   {
        Sheep sheep = null;
        try {
            sheep = (Sheep) super.clone();
        }catch (Exception e){
            e.printStackTrace();
        }
        return sheep;
    }
  
    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                 '}';
    }
}

用法:

public static main(String[] args) {
  Sheep sheep1 = new Sheep('sheep', 1);
  Sheep sheep2 = (Sheep)sheep1.clone();
}

如何处理深拷贝问题

  1. 重写clone方法,而不是仅仅是调用Object类的clone方法来实现深拷贝
  2. 通过对象序列化的方式来实现深拷贝

现在进行演示:

定义一个 程序员 类

public class Developer implements Serializable, Cloneable {
  	// 姓名;基本类型 + String 浅拷贝就可以搞定
    public String name;
    // 他的电脑;这里需要深拷贝才能搞定
		public Computer computer;
  
  	public Developer() {}
  
    //深拷贝-方式1 使用clone方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = null;
        //这里完成对基本数据类型(属性)和String类型的克隆
        obj = super.clone();
      
        //对应用类型的属性,进行单独处理
        Developer developer = (Developer) obj;
        developer.computer = (Computer) computer.clone();
        return developer;
    }
  
    // 深拷贝-方式2 通过对象的序列化实现(推荐)
    // 推荐原因,模版代码,不用修改,而上面的方式,每加减一个属性都有可能需要修改clone方法
    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);
            // 这里会分配新的内存空间来保存新对象,整个流数据拷贝过去
            Developer copyObj = (Developer) ois.readObject();
            return copyObj;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }finally {
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
        }
    }
}
定义Computer类
public class Computer implements Cloneable , Serializable {
    private String computerName;
  	
  	public Computer(String name) {
      computerName = name;
    }
  	
    //因为该类的属性都是string类型,因此我们这里使用默认的clone完成即可
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
使用:
public class Clinet {
    public static void main(String[] args) throws CloneNotSupportedException {
        Developer p = new Developer();
        p.name = "乔布斯";
        p.computer = new Computer("Macbook");

        Developer p2 = (Developer) p.deepClone();
        p.name = "库克";

        System.out.println("p.name=" + p.name + "  p.computer=" + p.computer.hashCode());
        System.out.println("p2.name=" + p2.name + "  p2.computer=" + p2.computer.hashCode());
    }
}

Developer类中定义了两种深拷贝的方式,推荐对象序列化的方式,因为clone的方式,每当类的属性有修改时,就有可能要修改clone方法;而序列化的方式不存在这种情况

posted @ 2021-09-30 22:52  明月照江江  阅读(21)  评论(0编辑  收藏  举报