Java 我应该在DTO中使用生成器模式吗?

Java 我应该在DTO中使用生成器模式吗?,java,design-patterns,dto,data-transfer-objects,builder-pattern,Java,Design Patterns,Dto,Data Transfer Objects,Builder Pattern,这可能是一个相当主观的问题,但我想知道更多的意见。我用SpringMVC构建了一个RESTAPI服务,并实现了DTO域实体模式。我想知道您如何看待在DTO中实现 public class UserResponseDTO extends AbstractResponseDTO { private String username; private Boolean enabled; public UserResponseDTO(String username, Bo

这可能是一个相当主观的问题,但我想知道更多的意见。我用SpringMVC构建了一个RESTAPI服务,并实现了DTO域实体模式。我想知道您如何看待在DTO中实现

public class UserResponseDTO
    extends AbstractResponseDTO {

    private String username;
    private Boolean enabled;

    public UserResponseDTO(String username, Boolean enabled) {
        this.username = username;
        this.enabled = enabled;
    }

    public String getUsername() {
        return this.username;
    }

    public Boolean getEnabled() {
        return this.enabled;
    }

    public static class Builder {

        private String username;
        private Boolean enabled;

        public void setUsername(String username) {
            this.username = username;
        }

        public void setEnabled(Boolean enabled) {
            this.enabled = enabled;
        }

        public UserResponseDTO build(){
            return new UserResponseDTO(username, enabled);
        }
    }
}
根据定义:

构建器设计模式的目的是将复杂对象的构造与其表示分离。通过这样做,相同的构造过程可以创建不同的表示

在我的大多数DTO案例中(不是说全部),我没有一个更复杂的对象要构建,比如这种情况。老实说,如果我们谈论DTO,我想不出任何构造复杂对象的例子

帮助使不可变对象更易于使用并使代码更清晰的模式之一是生成器模式

生成器模式提供不可变的对象。然后,我们可以认为DTO是服务响应本身,不应该被更改,因为这是一个响应(至少我是这么想的)



那你觉得呢?我是否应该将此模式用于DTO(考虑到这种情况,可能是大多数情况,不满足复杂对象原则)?

我的简短回答是,这是一个偏好问题。如果您喜欢生成器模式的工作方式,请应用它。对于这样一个小案件,我认为这两方面都无关紧要。我个人的偏好是不要在这里使用Builder,因为它似乎没有增加多少价值

我较长的回答是,构建器模式旨在简化复杂对象的配置,而无需求助于反模式(如伸缩构造函数)。在这种情况下,两种情况下都没有反模式;两种方案都相对较小且效率较高

虽然我们讨论的是首选项,但我更喜欢使用流畅界面的生成器模式的修改版本;每个方法都返回Builder的实例,以便方法调用可以链接在一起(而不是在单独的行上)。这与您链接的文章中的Java示例类似

我将修改您的生成器,使其如下所示:

public static class Builder {

        private String username;
        private Boolean enabled;

        public Builder setUsername(String username) {
            this.username = username;
            return this; 
        }

        public Builder setEnabled(Boolean enabled) {
            this.enabled = enabled;
            return this;
        }

        public UserResponseDTO build(){
            return new UserResponseDTO(username, enabled);
        }
    }
UserResponseDTO ur = new Builder().setUsername("user").setEnabled(true).build();
因此,使用构建器的外观如下所示:

public static class Builder {

        private String username;
        private Boolean enabled;

        public Builder setUsername(String username) {
            this.username = username;
            return this; 
        }

        public Builder setEnabled(Boolean enabled) {
            this.enabled = enabled;
            return this;
        }

        public UserResponseDTO build(){
            return new UserResponseDTO(username, enabled);
        }
    }
UserResponseDTO ur = new Builder().setUsername("user").setEnabled(true).build();

再说一次,这只是个人喜好的问题。

我看不出这里的建筑商甚至工厂有什么好处。然而,DTO通常是由DTO组装商组装的,这些组装商是工厂。我认为主要的动机是分离关注点,DTO的责任是作为数据容器,而汇编器的责任是很好地。。。组装DTO。我喜欢建筑工人。我喜欢用它们来创建不可变的对象。DTO的问题是不能使类不可变(至少在我们的情况下,它基本上阻止了喜欢POJO的Hibernate工作。)我有时会向DTO对象添加构建器,但我担心的是,无法通过代码强制使用它们。然后你会在其他地方编写对象创建逻辑。我不会使用构建器作为强制不变性的手段。提供一个没有setter的接口可能更容易。在生成bean时,实现对象将使用私有setter。客户端代码不需要访问实现类。Hibernate@Marvo的好处就在于此。人们不会使用构建器来强制实现不变性。但是构建器在强制类的正确实例化、避免难以阅读和使用“伸缩构造函数”方面很有用。但是,如果您不能以强制您使用构建器的方式更改类的设计(例如使其不可变并提供工厂或构建器),那么可能不熟悉代码的人会编写自己的实例化代码。谢谢大家!!我想我做得很好。Fluent builder是一个使用IMO的更干净的模式。谢谢!出色的回答