JAVA之原型模式

原型模式(Prototype Pattern)属于创建型模式,它允许一个对象通过复制自身来创建一个新的对象,而无需通过构造函数创建。这种模式特别适用于创建复杂对象时,避免构造函数的复杂性,同时提高性能。以下是关于原型模式的详细介绍、JAVA代码实现、运行结果及注释。

一、原型模式概述

定义

原型模式:用原型实例指定创建对象的种类,并通过复制这些原型创建新的对象。

主要角色

  • (1)抽象原型(Prototype)角色:定义具有克隆自身方法的接口。
  • (2)具体原型(ConcretePrototype)角色:实现抽象原型接口,实现克隆自身的方法。
  • (3)客户端(Client)角色:通过调用具体原型的克隆方法来创建新对象。

优点

  • (1)提高性能:通过复制现有对象,避免创建对象的初始化过程,提高性能。
  • (2)简化创建过程:无需通过构造函数创建对象,简化创建过程。
  • (3)动态创建对象:可根据需求动态地创建对象,提高代码的灵活性。

缺点

  • (1)深拷贝和浅拷贝:在实现克隆方法时,需要考虑深拷贝和浅拷贝的问题,增加实现难度。
  • (2)违背开闭原则:如果原型对象发生变化,需要修改克隆方法,可能导致原有代码受到影响。

二、JAVA代码实现

以下是一个简单的原型模式实现,以一个简历类为例:

java 复制代码
// 抽象原型接口,定义克隆方法
interface Resume extends Cloneable {
    Resume clone();
    void display();
}
// 具体原型角色,实现抽象原型接口
class ConcreteResume implements Resume {
    // 简历属性
    private String name;
    private String age;
    private String experience;
    // 构造函数
    public ConcreteResume(String name, String age, String experience) {
        this.name = name;
        this.age = age;
        this.experience = experience;
    }
    // 实现克隆方法
    @Override
    public Resume clone() {
        ConcreteResume resume = null;
        try {
            // 调用Object类的clone方法实现浅拷贝
            resume = (ConcreteResume) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return resume;
    }
    // 显示简历信息
    @Override
    public void display() {
        System.out.println("姓名:" + name);
        System.out.println("年龄:" + age);
        System.out.println("经历:" + experience);
    }
    // 省略getter和setter方法
}
// 客户端角色,测试原型模式
public class Client {
    public static void main(String[] args) {
        // 创建原型对象
        ConcreteResume resume = new ConcreteResume("张三", "25", "某公司实习");
        // 通过克隆方法创建新对象
        ConcreteResume resume1 = (ConcreteResume) resume.clone();
        ConcreteResume resume2 = (ConcreteResume) resume.clone();
        // 显示新对象信息
        resume1.display();
        System.out.println("-----------");
        resume2.display();
    }
}

运行结果:

java 复制代码
姓名:张三
年龄:25
经历:某公司实习
-----------
姓名:张三
年龄:25
经历:某公司实习

以上代码展示了原型模式的基本实现。在实际应用中,可以根据需求对原型对象进行扩展,实现深拷贝等功能。需要注意的是,原型模式适用于创建复杂对象,如果创建的对象较为简单,使用构造函数即可满足需求时,原型模式可能并不适用。下面,我们将继续深入探讨原型模式,并完成深拷贝的实现。

深拷贝与浅拷贝

在上面的例子中,我们实现了浅拷贝。浅拷贝只是复制了对象的所有基本类型的成员变量值,以及所有引用类型成员变量的引用值,而没有复制引用的对象本身。如果原型对象中包含引用类型成员变量,且这些引用指向的对象也需要被复制,那么就需要实现深拷贝。

实现深拷贝

要实现深拷贝,可以通过以下几种方式:

  1. 重写clone方法:在clone方法中,对引用类型成员变量也进行克隆。

  2. 通过序列化:先将对象序列化到流中,然后再从流中反序列化出来,得到一个全新的对象。 下面我们使用第一种方式来实现深拷贝:

java 复制代码
import java.io.Serializable;
// 抽象原型接口
interface Resume extends Cloneable, Serializable {
    Resume clone();
    void display();
}
// 具体原型角色
class ConcreteResume implements Resume {
    private String name;
    private String age;
    private WorkExperience workExperience; // 引用类型成员变量
    public ConcreteResume(String name, String age, WorkExperience workExperience) {
        this.name = name;
        this.age = age;
        this.workExperience = workExperience;
    }
    @Override
    public Resume clone() {
        ConcreteResume resume = null;
        try {
            resume = (ConcreteResume) super.clone();
            // 对引用类型成员变量进行深拷贝
            resume.workExperience = (WorkExperience) this.workExperience.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return resume;
    }
    @Override
    public void display() {
        System.out.println("姓名:" + name);
        System.out.println("年龄:" + age);
        System.out.println("工作经历:" + workExperience.getCompany() + " " + workExperience.getDuration());
    }
    // 省略getter和setter方法
}
// 工作经历类
class WorkExperience implements Cloneable, Serializable {
    private String company;
    private String duration;
    public WorkExperience(String company, String duration) {
        this.company = company;
        this.duration = duration;
    }
    @Override
    public WorkExperience clone() {
        WorkExperience workExperience = null;
        try {
            workExperience = (WorkExperience) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return workExperience;
    }
    // 省略getter和setter方法
    public String getCompany() {
        return company;
    }
    public String getDuration() {
        return duration;
    }
}
// 客户端角色
public class Client {
    public static void main(String[] args) {
        WorkExperience workExperience = new WorkExperience("某公司", "2019-2021");
        ConcreteResume resume = new ConcreteResume("张三", "25", workExperience);
        ConcreteResume resume1 = (ConcreteResume) resume.clone();
        ConcreteResume resume2 = (ConcreteResume) resume.clone();
        // 修改工作经历,以验证深拷贝
        workExperience.setCompany("新公司");
        workExperience.setDuration("2022-至今");
        resume1.display();
        System.out.println("-----------");
        resume2.display();
    }
}

运行结果:

java 复制代码
姓名:张三
年龄:25
工作经历:某公司 2019-2021
-----------
姓名:张三
年龄:25
工作经历:某公司 2019-2021

在上面的代码中,我们添加了一个WorkExperience类,并在ConcreteResume类中引入了该类的实例作为成员变量。在ConcreteResumeclone方法中,我们对workExperience成员变量也进行了克隆,从而实现了深拷贝。

原型模式的优缺点

优点
  1. 提高性能:当创建新的对象实例较为复杂且耗时时,原型模式可以简化对象的创建过程,提高性能。

  2. 简化创建过程:通过复制现有实例来创建新实例,避免了复杂的构造函数调用。

  3. 保护性拷贝:原型模式可以在运行时保护性地拷贝对象,避免外部直接修改对象状态。

缺点
  1. 深拷贝实现复杂:如果对象之间存在复杂的引用关系,实现深拷贝可能会比较困难。

  2. 违背开闭原则:如果原型对象发生变化,则所有通过克隆创建的对象都需要进行相应的修改。

总结

原型模式通过复制现有对象来创建新对象,适用于创建复杂对象的情况。在实现原型模式时,需要注意浅拷贝和深拷贝的区别,并根据实际需求选择合适的拷贝方式。通过上述代码示例,我们可以看到原型模式在Java中的具体实现,以及如何通过深拷贝来保持对象间的独立性。

相关推荐
2403_8751809523 分钟前
一键掌握多平台短视频矩阵营销/源码部署
java·前端·数据结构·线性代数·矩阵·php
向阳121838 分钟前
doris:手动分区
java·服务器·windows·doris
angen20181 小时前
二十三种模式-适配器模式
java
我是苏苏1 小时前
设计模式02:结构型设计模式之适配器模式使用情景及其基础Demo
java·设计模式·适配器模式
昔我往昔2 小时前
Spring Boot中如何处理跨域请求(CORS)
java·spring boot·后端
昔我往昔2 小时前
Spring Boot中的配置文件有哪些类型
java·spring boot·后端
qingy_20463 小时前
【算法】图解排序算法之归并排序、快速排序、堆排序
java·数据结构·算法
张声录13 小时前
【ETCD】【源码阅读】深入探索 ETCD 源码:了解 `Range` 操作的底层实现
java·数据库·etcd
Zhu_S W3 小时前
SpringBoot 自动装配原理及源码解析
java·spring boot·spring
爱晒太阳的小老鼠3 小时前
apisix的etcd使用
java·etcd