【Java 设计模式】创建者模式 之原型模式

§1 定义

  • 将一个已经创建好的实例作为原型,通过复制该原型对象来创建一个和原型对象相同对象。

§2 角色

  • 抽象原型类:定义具体原型类需要实现的 clone 方法,对于 Java 来说,具体原型类直接实现 Cloneable 接口重写 clone 方法即可,无需再重新定义抽象原型类。
  • 具体原型类:实现抽象原型类的 clone 方法。
  • 访问类:使用具体原型类中的 clone 方法复制新对象。

§3 三好学生案例

  • 班级里有多名同学获得了三好学生的奖状,除了奖状上的获奖人姓名不一样外,其他都是一样的,使用原型模式复制出多个三好学生奖状,然后修改奖状上的名字。

§3.1 浅克隆实现

§3.1.1 浅克隆定义

  • 创建一个新的对象,新对象的属性和原型对象的完全相同,对于非基本类型的属性,仍然指向原型对象所指向的对象的内存地址

§3.1.2 类图

在这里插入图片描述

§3.1.3 实现

// 具体原型类: 奖状
public class Citation implements Cloneable {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void show() {
        System.out.println("三好学生:" + name);
    }
    @Override
    protected Citation clone() throws CloneNotSupportedException {
        return (Citation) super.clone();
    }
}

// 访问类
public class CitationTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Citation c1 = new Citation();
        c1.setName("张三");
        Citation c2 = c1.clone();
        c2.setName("李四");
        c1.show();
        c2.show();
    }
}
/* 输出结果:
三好学生:张三
三好学生:李四
*/
  • 浅克隆模式看似一切正常,若我们把 Citation 的 name 属性改为 Student 自定义对象,再来看看会发生什么?
// 学生类
public class Student {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

// 具体原型类: 奖状
public class Citation implements Cloneable {
    private Student student;
    public Student getStudent() {
        return student;
    }
    public void setStudent(Student student) {
        this.student = student;
    }
    public void show() {
        System.out.println("三好学生:" + student.getName());
    }
    @Override
    protected Citation clone() throws CloneNotSupportedException {
        return (Citation) super.clone();
    }
}

// 访问类
public class CitationTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Citation c1 = new Citation();
        Student student1 = new Student();
        student1.setName("张三");
        c1.setStudent(student1);
        Citation c2 = c1.clone();
        Student student2 = c2.getStudent();
        student2.setName("李四");
        System.out.println("student1和student2是同一个对象吗?" + (student1 == student2));
        c1.show();
        c2.show();
    }
}
/* 输出结果:
student1和student2是同一个对象吗?true
三好学生:李四
三好学生:李四
*/
  • 测试结果可以看出,两个 student 对象是同一个对象,当修改克隆后的学生名字时,原型对象的名字也被修改了,这是浅克隆方式的弊端。可以使用深克隆方式解决。

§3.2 深克隆实现

§3.2.1 深克隆定义

  • 创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象的地址。

§3.2.2 实现

// 学生类
public class Student implements Serializable {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

// 具体原型类: 奖状
public class Citation implements Cloneable, Serializable {
    private Student student;
    public Student getStudent() {
        return student;
    }
    public void setStudent(Student student) {
        this.student = student;
    }
    public void show() {
        System.out.println("三好学生:" + student.getName());
    }
    @Override
    protected Citation clone() throws CloneNotSupportedException {
        return (Citation) super.clone();
    }
}

// 访问类
public class CitationTest {
    public static void main(String[] args) throws Exception {
        Citation c1 = new Citation();
        Student student1 = new Student();
        student1.setName("张三");
        c1.setStudent(student1);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\study\\a.txt"));
        oos.writeObject(c1);
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\study\\a.txt"));
        Citation c2 = (Citation) ois.readObject();
        ois.close();
        Student student2 = c2.getStudent();
        student2.setName("李四");
        System.out.println("student1和student2是同一个对象吗?" + (student1 == student2));
        c1.show();
        c2.show();
    }
}
/* 输出结果:
student1和student2是同一个对象吗?false
三好学生:张三
三好学生:李四
*/
  • 使用序列化和反序列化的方式实现深克隆,解决浅克隆的弊端。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

准Java全栈开发工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值