首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >5分钟聊一聊Java中的原型模式

5分钟聊一聊Java中的原型模式

原创
作者头像
努力的小雨
发布2024-08-14 09:24:25
发布2024-08-14 09:24:25
2720
举报
文章被收录于专栏:灵墨AI探索室灵墨AI探索室

在软件开发中,处理对象的创建和管理往往是一个重要的任务。特别是在面对复杂对象时,传统的创建方法可能会导致高昂的时间和资源消耗。原型模式(Prototype Pattern)作为一种创建型设计模式,通过克隆现有对象来创建新对象,从而显著提高了对象创建的效率。本文将深入探讨原型模式的深复制和浅复制,并介绍如何结合 MapStruct 工具类进行对象转换。

原型模式概述

原型模式的核心思想是通过复制现有对象来创建新对象,而不是通过构造函数逐步初始化对象。这样可以避免重复的初始化过程,从而节省时间和资源。尤其在对象创建过程复杂或昂贵的情况下,原型模式能够显著提高效率。它通常用于那些对象创建复杂且开销大的场景,如图形对象、配置对象等。

浅复制与深复制

在实现原型模式时,克隆操作的实现方式主要有两种:浅复制(Shallow Copy)和深复制(Deep Copy)。这两种复制方法在处理对象的内部数据时有所不同。

浅复制

浅复制是指在克隆对象时,仅复制对象的基本数据类型字段和对引用类型字段的引用,而不是这些引用对象本身。这意味着,原对象和克隆对象共享同一个引用类型字段。如果原对象中的引用字段发生改变,克隆对象的相应字段也会受到影响。

以下是一个浅复制的示例代码:

代码语言:java
复制
import java.util.Date;

public class Sheep implements Cloneable {
    private String name;
    private Date birth;

    public Sheep(String name, Date birth) {
        this.name = name;
        this.birth = birth;
    }

    @Override
    protected Object clone() {
        Sheep obj = null;
        try {
            obj = (Sheep) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return obj;
    }

    public String getName() {
        return name;
    }

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

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }
}

在这个示例中,Sheep 类实现了 Cloneable 接口,并重写了 clone 方法来实现浅复制。复制后的 Sheep 对象与原对象共享 birth 字段的引用。如果我们修改原对象的 birth 日期,新对象的 birth 日期也会改变。

深复制

深复制是指在克隆对象时,不仅复制对象的基本数据类型字段,还递归地复制对象引用的所有对象。这意味着克隆对象与原对象完全独立,彼此之间没有共享的引用。因此,对一个对象的修改不会影响其他对象。

以下是一个进行深复制的示例代码:

代码语言:java
复制
import java.util.Date;

public class Sheep implements Cloneable {
    private String name;
    private Date birth;

    public Sheep(String name, Date birth) {
        this.name = name;
        this.birth = birth;
    }

    @Override
    protected Object clone() {
        Sheep obj = null;
        try {
            obj = (Sheep) super.clone();
            obj.birth = (Date) this.birth.clone(); // 深复制
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return obj;
    }

    public String getName() {
        return name;
    }

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

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }
}

在这个深复制的实现中,我们在 clone 方法中添加了 birth 字段的深复制逻辑。这样,每个 Sheep 对象都拥有自己的 Date 实例。即使我们修改了原对象的 birth 日期,新对象的 birth 日期仍然保持不变。

使用 MapStruct 进行对象转换

MapStruct 是一个用于对象映射的开源框架,它通过编译时生成代码来简化 Java 对象之间的数据转换。MapStruct 提供了一种高效的方式来将一个对象的属性映射到另一个对象,特别适合用于数据传输对象(DTO)和业务对象(BO)之间的转换。

配置 MapStruct

首先,我们需要在项目中添加 MapStruct 的依赖。对于 Maven 项目,pom.xml 中需要加入以下内容:

代码语言:xml
复制
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
    <scope>provided</scope>
</dependency>

对于 Gradle 项目,可以在 build.gradle 文件中添加:

代码语言:groovy
复制
implementation 'org.mapstruct:mapstruct:1.5.5.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'

定义映射接口

MapStruct 使用接口定义映射规则。我们可以创建一个映射接口来将 Sheep 对象转换为 SheepDTO 对象。

代码语言:java
复制
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface SheepMapper {
    SheepMapper INSTANCE = Mappers.getMapper(SheepMapper.class);

    SheepDTO sheepToSheepDTO(Sheep sheep);
    Sheep sheepDTOToSheep(SheepDTO sheepDTO);
}

定义数据传输对象(DTO)

创建 SheepDTO 类作为转换的目标对象:

代码语言:java
复制
public class SheepDTO {
    private String name;
    private Date birth;

    // getters and setters
}

使用 MapStruct 进行对象转换

在实际应用中,可以使用 MapStruct 提供的映射功能来进行对象转换。例如:

代码语言:java
复制
import java.util.Date;

public class Client {
    public static void main(String[] args) {
        Date date = new Date(1723453691L);
        Sheep sheep = new Sheep("s1", date);

        // 使用 MapStruct 进行转换
        SheepDTO sheepDTO = SheepMapper.INSTANCE.sheepToSheepDTO(sheep);
        System.out.println("SheepDTO Birth: " + sheepDTO.getBirth());

        // 修改原始对象
        date.setTime(15L);
        System.out.println("Original Sheep Birth: " + sheep.getBirth());
        System.out.println("Converted SheepDTO Birth: " + sheepDTO.getBirth());
    }
}

在这个示例中,我们通过 SheepMapperSheep 对象转换为 SheepDTO 对象。这样,我们能够高效地将对象数据传递到不同的模型中,而不必手动编写繁琐的转换代码。

注意,本演示过程中所有对象的属性完全一致的,如果属性不一致的情况下,使用MapStruct需要特别指定

BeanUtils.copyProperties

在 Java 中,BeanUtils.copyProperties 方法是 Apache Commons BeanUtils 库提供的一个用于对象属性复制的工具。这种方法虽然在某些场景下非常便利,但在处理复杂对象映射时存在一些劣势。相比之下,MapStruct 提供了更为强大和灵活的映射功能,特别是在性能和自定义映射规则方面。

BeanUtils.copyProperties 是基于反射实现的。反射操作通常比直接访问对象属性慢得多,因为反射需要在运行时解析类型信息和方法。这种性能开销在大规模的数据转换或者高频调用时可能会成为瓶颈。

代码语言:java
复制
import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.InvocationTargetException;

public class Client {
    public static void main(String[] args) {
        Source source = new Source("xiaoyu", 30);
        Target target = new Target();
        try {
            BeanUtils.copyProperties(target, source);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println(target.getName()); // xiaoyu
        System.out.println(target.getAge());  // 30
    }
}

总结

原型模式通过克隆对象来提高创建复杂对象的效率,避免了重复的初始化步骤。浅复制和深复制是实现克隆的两种主要方式,浅复制简单但可能导致共享引用的问题,而深复制则更加全面但开销更大。结合 MapStruct 工具类,可以进一步提高对象转换的效率,简化数据传递和处理过程。通过合理地选择克隆方式和使用 MapStruct 进行对象转换,开发者可以在处理复杂对象时实现更高效、更具可维护性的解决方案。


我是努力的小雨,一名 Java 服务端码农,潜心研究着 AI 技术的奥秘。我热爱技术交流与分享,对开源社区充满热情。同时也是一位掘金优秀作者、腾讯云创作之星、阿里云专家博主、华为云云享专家。

💡 我将不吝分享我在技术道路上的个人探索与经验,希望能为你的学习与成长带来一些启发与帮助。

🌟 欢迎关注努力的小雨!🌟

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原型模式概述
    • 浅复制与深复制
      • 浅复制
      • 深复制
    • 使用 MapStruct 进行对象转换
      • 定义映射接口
      • 定义数据传输对象(DTO)
      • 使用 MapStruct 进行对象转换
    • BeanUtils.copyProperties
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档