这是dtos中构建器模式的正确用法吗?

时间:2017-07-05 23:01:32

标签: java spring design-patterns

假设我有PostDTO,其中包含以下字段:

private Long id;
private ShortInfoUserDTO author;
private CategoryDTO category;

我在其中有CategoryDTO,它也有Builder,它有字段:

private Long id;
private String name;

ShortInfoUserDTO有一些字段(无论哪个字段都有,但它也有Builder)

我的构建器模式看起来像这样(CategoryDTO和

public static Builder builder() {
    return new PostDTO.Builder();
}
public static class Builder {
    PostDTO instance = new PostDTO();        

    public Builder id(Long id) {
        instance.id = id;
        return this;
    }

    public Builder author(User user) {
        ShortInfoUserDTO author = ShortInfoUserDTO.builder()
                                                  .id(user.getId())
                                            .username(user.getUsername())
                                            .build();
        instance.author = author;
        return this;
    }



    public Builder category(Category category) {
          CategoryDTO categoryDto = CategoryDTO
                                      .builder()
                                      .id(category.getId())
                                      .name(category.getName())
                                      .build();           

          instance.category = categoryDto;            
          return this;
    }

    public PostDTO build() {
        return instance;
    }
}

一般是建立author()和category()的想法这样好吗?喜欢这个合适的建筑吗?我问的原因之一是因为我有点担心nullpointerexceptions

1 个答案:

答案 0 :(得分:1)

嗯,只要您能够使用这些样板代码,这是构建POJO的一种非常简洁的方法。

Lombok builder可以帮助您减少样板量。

另一种方法是使用映射工具而不是手动DTO构造。例如,请查看ModelMapper

使用mapper,您可以执行以下操作:

public class So44937295ApplicationTests {
    final ModelMapper modelMapper = new ModelMapper();

    @Test
    public void manual() {
        final User user = new User();
        user.setId(42L);
        user.setUsername("John");
        user.setPassword("goof");

        final Category category = new Category();
        category.setId(23L);
        category.setName("Category 1");

        final PostDTO postDTO = new PostDTO();
        postDTO.setAuthor(modelMapper.map(user, ShortInfoUserDTO.class));
        postDTO.setCategory(modelMapper.map(category, CategoryDTO.class));

        assertEquals(user.getId(), postDTO.getAuthor().getId());
        assertEquals(user.getUsername(), postDTO.getAuthor().getUsername());

        assertEquals(category.getId(), postDTO.getCategory().getId());
        assertEquals(category.getName(), postDTO.getCategory().getName());
    }

    @Test
    public void auto() {
        final User user = new User();
        user.setId(42L);
        user.setUsername("John");
        user.setPassword("goof");

        final Category category = new Category();
        category.setId(23L);
        category.setName("Category 1");

        class Post {
            private User author;
            private Category category;
            // getters and setters
        }

        final Post post = new Post();
        post.setAuthor(user);
        post.setCategory(category);
        final PostDTO postDTO = modelMapper.map(post, PostDTO.class);

        assertEquals(post.getAuthor().getId(), postDTO.getAuthor().getId());
        assertEquals(post.getAuthor().getUsername(), postDTO.getAuthor().getUsername());

        assertEquals(post.getCategory().getId(), postDTO.getCategory().getId());
        assertEquals(post.getCategory().getName(), postDTO.getCategory().getName());
    }

    public static class PostDTO {
        private Long id;
        private ShortInfoUserDTO author;
        private CategoryDTO category;
        // getters and setters
    }

    public static class User {
        private Long id;
        private String username;
        private String password;
        // getters and setters
    }

    public static class ShortInfoUserDTO {
        private Long id;
        private String username;
        // getters and setters
    }

    public static class Category {
        private Long id;
        private String name;
        // getters and setters
    }

    public static class CategoryDTO {
        private Long id;
        private String name;
        // getters and setters
    }

}

所有转换逻辑都将使用反射(基于字段名称)为您完成。您可以配置该行为。