小易说IT 小易说IT

Java原型模式(Prototype)代码示例

原型模式:通过复制已有对象(原型)来创建新对象,而不是 new 新建对象,适合对象创建成本高的场景。 Java 两种实现方式:

  1. 实现 Cloneable 接口,重写 clone()(浅拷贝)

  2. 序列化实现深拷贝

1、浅拷贝示例(Cloneable)

原型对象

// 实现Cloneable标记接口
class Sheep implements Cloneable {
    private String name;
    private int age;
    // 引用类型成员,浅拷贝会共用同一个对象
    private Friend friend;

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

    // 重写clone,浅拷贝
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    // getter setter toString
    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 Friend getFriend() { return friend; }
    public void setFriend(Friend friend) { this.friend = friend; }

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

// 引用类
class Friend {
    private String nickName;

    public Friend(String nickName) {
        this.nickName = nickName;
    }

    public String getNickName() { return nickName; }
    public void setNickName(String nickName) { this.nickName = nickName; }

    @Override
    public String toString() {
        return "Friend{" + "nickName='" + nickName + '\'' + '}';
    }
}

客户端测试

public class PrototypeDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        // 原始原型对象
        Friend friend = new Friend("小黑");
        Sheep original = new Sheep("多利", 2, friend);

        // 使用原型克隆对象
        Sheep cloneSheep = (Sheep) original.clone();

        System.out.println("原对象:" + original);
        System.out.println("克隆对象:" + cloneSheep);

        System.out.println("====================");
        System.out.println("对象地址是否相同:" + (original == cloneSheep));
        // 浅拷贝:引用类型还是同一个对象
        System.out.println("friend引用是否同一对象:" + (original.getFriend() == cloneSheep.getFriend()));

        // 修改克隆对象里的引用属性,原对象也会被影响【浅拷贝坑点】
        cloneSheep.getFriend().setNickName("小白");
        System.out.println("\n修改克隆对象的引用属性后");
        System.out.println("原对象:" + original);
        System.out.println("克隆对象:" + cloneSheep);
    }
}

浅拷贝效果:基本数据类型复制值;引用类型只复制引用地址,新旧对象指向同一个子对象


2、深拷贝实现(两种方式)

方式 1:clone 手动递归拷贝引用对象

class SheepDeep implements Cloneable {
    private String name;
    private int age;
    private Friend friend;

    public SheepDeep(String name, int age, Friend friend) {
        this.name = name;
        this.age = age;
        this.friend = friend;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 先拷贝基础属性
        SheepDeep sheep = (SheepDeep) super.clone();
        // 手动克隆引用对象,新建Friend
        sheep.friend = new Friend(this.friend.getNickName());
        return sheep;
    }

    // getter setter toString
    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 Friend getFriend() { return friend; }
    public void setFriend(Friend friend) { this.friend = friend; }

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

方式 2:序列化实现通用深拷贝(推荐,多层对象不用手动写 clone)

所有参与对象实现 Serializable

import java.io.*;

/**
 * 序列化工具实现深拷贝
 */
public class DeepCloneUtil {
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T deepClone(T obj) {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            // 序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);

            // 反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            return (T) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if(oos != null) oos.close();
                if(bos != null) bos.close();
                if(ois != null) ois.close();
                if(bis != null) bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

实体类增加序列化标记:

import java.io.Serializable;

class Friend implements Serializable {
    // ...原有代码
}

class Sheep implements Serializable {
    // ...原有代码
}

调用:

Sheep clone = DeepCloneUtil.deepClone(original);

3、原型模式 UML 角色说明

  1. Prototype(原型抽象):声明克隆自身的接口(Cloneable

  2. ConcretePrototype(具体原型):实现克隆方法(Sheep)

  3. Client(客户端):拿到原型对象,调用 clone 复制出新对象

4、适用场景

  1. 对象创建成本很高(大量 IO、数据库查询),复制比 new 性能更好

  2. 需要大量相似对象,仅少量属性不同

  3. 保护原有对象,不希望直接修改原型实例

5、注意点

  • Cloneable 只是标记接口,没有任何方法,不重写 clone 会抛异常

  • Object.clone() 默认是浅拷贝,包含引用类型要做深拷贝

  • 序列化深拷贝性能略差,但支持任意层级对象;手动 clone 性能好,嵌套对象多时代码繁琐