Java设计模式之原型模式详细解析

 更新时间:2023年11月23日 10:45:59   作者:Super_Leng  
这篇文章主要介绍了Java设计模式之原型模式详细解析,原型模式就是用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象,需要的朋友可以参考下

一、原型模式

1. 概述

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

2. 结构

原型模式包含如下角色:

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

接口类图如下:

在这里插入图片描述

3. 实现

原型模式的克隆分为浅克隆和深克隆。

  • 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
  • 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

Java中的Object类中提供了 clone() 方法来实现浅克隆。

Cloneable 接口是上面的类图中的抽象原型类,而实现了Cloneable接口的子实现类就是具体的原型类。

Realizetype(具体的原型类):

public class Realizetype implements Cloneable {

    public Realizetype() {
        System.out.println("具体的原型对象创建完成!");
    }

    @Override
    public Realizetype clone() throws CloneNotSupportedException {
        System.out.println("具体原型复制成功!");

        return (Realizetype) super.clone();
    }
}

PrototypeTest(测试访问类):

public class PrototypeTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        //创建一个原型类对象
        Realizetype realizetype = new Realizetype();

        //调用Realizetype类中的clone方法进行对象的克隆
        Realizetype clone = realizetype.clone();

        System.out.println("原型对象和克隆出来的是否是同一个对象?" + (realizetype == clone));
    }
}

运行结果为:

在这里插入图片描述

4. 案例

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

同一学校的“三好学生”奖状除了获奖人姓名不同,其他都相同,可以使用原型模式复制多个“三好学生”奖状出来,然后在修改奖状上的名字即可。

在这里插入图片描述

奖状类:

public class Citation implements Cloneable {
    private String name;

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

    public String getName() {
        return (this.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();
    }
}

运行结果为:

在这里插入图片描述

5 使用场景

  • 对象的创建非常复杂,可以使用原型模式快捷的创建对象。
  • 性能和安全要求比较高。

6 扩展(深克隆)

将上面的“三好学生”奖状的案例中Citation类的name属性修改为Student类型的属性。

奖状类:

public class Citation implements Cloneable {
    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 {
    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 CitationTest {
    public static void main(String[] args) throws CloneNotSupportedException {

        Citation c1 = new Citation();
        Student stu = new Student("张三", "西安");
        c1.setStu(stu);

        //复制奖状
        Citation c2 = c1.clone();
        //获取c2奖状所属学生对象
        Student stu1 = c2.getStu();
        stu1.setName("李四");

        //判断stu对象和stu1对象是否是同一个对象
        System.out.println("stu和stu1是同一个对象?" + (stu == stu1));

        c1.show();
        c2.show();
    }
}

运行结果为:

在这里插入图片描述

说明: ​ stu对象和stu1对象是同一个对象,就会产生将stu1对象中name属性值改为“李四”,两个Citation(奖状)对象中显示的都是李四。

这就是浅克隆的效果,对具体原型类(Citation)中的引用类型的属性进行引用的复制。

这种情况需要使用深克隆,而进行深克隆需要使用对象流。

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"));
        //将c1对象写出到文件中
        oos.writeObject(c1);
        oos.close();

        //创建对象出入流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\Think\\Desktop\\b.txt"));
        //读取对象
        Citation c2 = (Citation) ois.readObject();
        //获取c2奖状所属学生对象
        Student stu1 = c2.getStu();
        stu1.setName("李四");

        //判断stu对象和stu1对象是否是同一个对象
        System.out.println("stu和stu1是同一个对象?" + (stu == stu1));

        c1.show();
        c2.show();
    }
}

运行结果为:

在这里插入图片描述

注意:Citation类和Student类必须实现Serializable接口,否则会抛NotSerializableException异常。

到此这篇关于Java设计模式之原型模式详细解析的文章就介绍到这了,更多相关Java中的原型模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Springboot Thymeleaf模板文件调用Java类静态方法

    Springboot Thymeleaf模板文件调用Java类静态方法

    这篇文章主要介绍了Springboot Thymeleaf模板文件调用Java类静态方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2007-09-09
  • Springboot JPA 枚举Enum类型存入到数据库的操作

    Springboot JPA 枚举Enum类型存入到数据库的操作

    这篇文章主要介绍了Springboot JPA 枚举Enum类型存入到数据库的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • Spring Boot 集成Dubbo框架实例

    Spring Boot 集成Dubbo框架实例

    本篇文章主要介绍了Spring Boot 集成Dubbo框架实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • java增强for循环的实现方法

    java增强for循环的实现方法

    下面小编就为大家带来一篇java增强for循环的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • C#中NAudio音频库的安装与使用教程详解

    C#中NAudio音频库的安装与使用教程详解

    NAudio为.NET平台下的开源库,采用ML-PL协议,它支持许多音频操作,可实现多种API播放与录制、多种不同音频格式等功能,下面就跟随小编一起学习一下NAudio的安装与使用吧
    2023-11-11
  • Java自定义实现equals()方法过程解析

    Java自定义实现equals()方法过程解析

    这篇文章主要介绍了Java自定义实现equals()方法过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • SpringBoot升级3.2报错Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String的解决方案

    SpringBoot升级3.2报错Invalid value type for 

    这篇文章给大家介绍了SpringBoot升级3.2报错Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String的解决方案,文中有详细的原因分析,需要的朋友可以参考下
    2023-12-12
  • 浅谈Java设置PPT幻灯片背景——纯色、渐变、图片背景

    浅谈Java设置PPT幻灯片背景——纯色、渐变、图片背景

    这篇文章主要介绍了Java设置PPT幻灯片背景——纯色、渐变、图片背景,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Java SpringMVC的@RequestMapping注解使用及说明

    Java SpringMVC的@RequestMapping注解使用及说明

    这篇文章主要介绍了Java SpringMVC的@RequestMapping注解使用及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • Java匿名内部类的使用方法举例详解

    Java匿名内部类的使用方法举例详解

    Java中的匿名内部类是一种没有名字的局部内部类,主要用于一次性实现接口或继承类的场合,它们常见于GUI事件处理、多线程编程等场景,简化代码结构同时提高开发效率,需要的朋友可以参考下
    2024-09-09

最新评论