博客
关于我
设计模式_创建型模式 -《原型模式》
阅读量:796 次
发布时间:2023-03-25

本文共 4198 字,大约阅读时间需要 13 分钟。

设计模式_创建型模式 - 原型模式

原型模式(Prototype Pattern)是一种创建型设计模式,通过使用一个已经创建的实例作为原型,来创建一个与原型对象相同的新对象。这种模式在软件开发中非常有用,特别是在对象的创建过程复杂或资源消耗高时。


概述

原型模式的核心思想是:用一个原型对象作为模板,通过复制该原型对象来创建新的对象。这种方式可以减少新对象创建时的资源消耗,同时保持新对象与原型对象之间的一致性。


结构

原型模式的主要角色包括:

  • 抽象原型类:规定了具体原型对象必须实现的 clone() 方法。
  • 具体原型类:实现了抽象原型类的 clone() 方法,且是可以被复制的对象。
  • 访问类:使用具体原型类中的 clone() 方法来创建新对象。
  • 类图如下:

     

    接口类图如下:

     

    实现

    在 Java 中,Object 类中的 clone() 方法默认实现了浅克隆(Shallow Copy)。Cloneable 接口是抽象原型类,具体原型类需要实现这个接口。

    浅克隆(Shallow Copy)

    • 浅克隆会创建一个新对象,新对象的属性与原对象完全相同。
    • 对于非基本类型属性,新对象仍然引用原对象所指向的内存地址。

    深克隆(Deep Copy)

    • 深克隆会创建一个新对象,新对象的属性中引用的其他对象也会被克隆。
    • 新对象的引用的对象地址与原对象不同。

    要实现深克隆,需使用序列化(Serializable)接口,并通过对象流(ObjectInputStream 和 ObjectOutputStream)进行操作。

    示例代码

    // 实现Cloneable接口的具体原型类
    public class Realizetype implements Cloneable {
    public Realizetype() {
    System.out.println("具体的原型对象创建完成!");
    }
    @Override
    protected Realizetype clone() throws CloneNotSupportedException {
    System.out.println("具体原型复制成功!");
    return (Realizetype) super.clone();
    }
    }
    // 测试访问类
    public class PrototypeTest {
    public static void main(String[] args) throws CloneNotSupportedException {
    Realizetype r1 = new Realizetype();
    Realizetype r2 = r1.clone();
    System.out.println("r1和r2是否是同一个对象?" + (r1 == r2)); // 输出: false
    }
    }

    案例

    用原型模式生成“三好学生”奖状

    假设我们需要生成多个具有相同属性的“三好学生”奖状,只需复制一个奖状并修改其中的姓名即可。

    奖状类(实现Cloneable接口)
    public class Citation implements Cloneable {
    private String name;
    public void setName(String name) {
    this.name = name;
    }
    public String getName() {
    return name;
    }
    public void show() {
    System.out.println(name + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }
    @Override
    public 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();
    }
    }

    输出结果:

    张三同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!
    李四同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!

    使用场景

  • 对象创建复杂,通过复制现有对象来减少开发时间。
  • 需要确保对象的安全性,防止多个对象共享同一个状态。

  • 总结

    • 克隆操作会在堆中创建新的对象,原对象与克隆对象的内存地址不同。
    • 对于引用类型的属性,浅克隆只复制了引用地址,而不会创建新对象。
    • 深克隆需要实现序列化,才能确保引用对象也被复制。

    扩展(深克隆)

    要实现深克隆,需使用序列化接口,并通过对象流进行操作。

    示例代码(深克隆)

    // 实现序列化接口的具体原型类
    public class Citation implements Serializable {
    private Student stu;
    public Student getStu() {
    return stu;
    }
    public void setStu(Student stu) {
    this.stu = stu;
    }
    void show() {
    System.out.println(stu.getName() + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
    }
    @Override
    public Citation clone() throws CloneNotSupportedException {
    return (Citation) super.clone();
    }
    }
    // 实现序列化接口的学生类
    public class Student implements Serializable {
    private String name;
    private String address;
    public Student(String name, String address) {
    this.name = name;
    this.address = address;
    }
    public Student() {
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getAddress() {
    return address;
    }
    public void setAddress(String address) {
    this.address = address;
    }
    }

    测试类(深克隆)

    public class CitationTest1 {
    public static void main(String[] args) throws Exception {
    Citation c1 = new Citation();
    Student stu = new Student("张三", "西安");
    c1.setStu(stu);
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\Think\\Desktop\\b.txt"));
    oos.writeObject(c1);
    oos.close();
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\Think\\Desktop\\b.txt"));
    Citation c2 = (Citation) ois.readObject();
    ois.close();
    Student stu1 = c2.getStu();
    stu1.setName("李四");
    System.out.println("stu和stu1是否是同一个对象?" + (stu == stu1)); // 输出: false
    c1.show();
    c2.show();
    }
    }

    运行结果:

    stu和stu1不是同一个对象。
    张三同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!
    李四同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!

    说明:stustu1 是同一个对象的引用,但 stu1name 属性已修改为“李四”。

    转载地址:http://szhfk.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现Romberg算法(附完整源码)
    查看>>
    Objective-C实现RRT路径搜索(附完整源码)
    查看>>
    Objective-C实现rsa 密钥生成器算法(附完整源码)
    查看>>
    Objective-C实现RSA密码算法(附完整源码)
    查看>>
    Objective-C实现runge kutta龙格-库塔法算法(附完整源码)
    查看>>
    Objective-C实现segment tree段树算法(附完整源码)
    查看>>
    Objective-C实现selection sort选择排序算法(附完整源码)
    查看>>
    Objective-C实现sha256算法(附完整源码)
    查看>>
    Objective-C实现shell sort希尔排序算法(附完整源码)
    查看>>
    Objective-C实现SinglyLinkedList单链表算法(附完整源码)
    查看>>
    Objective-C实现skew heap倾斜堆算法(附完整源码)
    查看>>
    Objective-C实现Skip List跳表算法(附完整源码)
    查看>>
    Objective-C实现slack message松弛消息算法(附完整源码)
    查看>>
    Objective-C实现slow sort慢排序算法(附完整源码)
    查看>>
    Objective-C实现tanh函数功能(附完整源码)
    查看>>
    Objective-C实现z-algorithm算法(附完整源码)
    查看>>
    Objective-C实现zellers congruence泽勒一致算法(附完整源码)
    查看>>
    Objective-C实现Zero One Knapsack零一背包计算算法(附完整源码)
    查看>>
    Objective-C实现一个Pangram字符串至少包含一次所有字母算法(附完整源码)
    查看>>
    Objective-C实现一个通用的堆算法(附完整源码)
    查看>>