建造者模式构建javabean

今天写一个构建者模式,通常我们使用javaBean都是定义私有属性,生成getset方法。这种方式很常见,在属性较少的时候,可以很好地使用,但是一旦属性爆炸时,那么意味着我们会有无穷无尽的set代码要写。比如我们现在一个主表有50个字段左右,还有请求别人接口时,dto也有50多个属性字段要写。那么每次持久化之前或者发送之前的报文组装,都要set属性值。有时候写着写着自己就乱了。有可能存错值。或者在你成功组装好dto或者javabean之后,后续的代码无意中set了一个错值。那么这个值就会被持久化或者发送出去。那么这次请求就算是出错了。所以为了避免这样的情况发生。也避免自己写set写吐了。我们可以使用建造者模式创建一个对象。

好了话不多说,直接上代码。

这是我手写的一个建造者javabean

public class TestUser {

    private final int id;
    private final String name;
    private final int age;
    private final List<String> items;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public List<String> getItems() {
        return items;
    }

    @Override
    public String toString() {
        return "TestUser{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", items=" + items +
                '}';
    }

    private TestUser(int id, String name, int age, List<String> items) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.items = items;
    }

    public static testUserBuilder builder(){
        return new testUserBuilder();
    }

    public static class testUserBuilder{

        private int id;
        private String name;
        private int age;
        private List<String> items;

        public testUserBuilder id(int id){
            this.id = id;
            return this;
        }

        public testUserBuilder name(String name){
            this.name = name;
            return this;
        }

        public testUserBuilder age(int age) {
            this.age = age;
            return this;
        }

        public testUserBuilder items(List<String> items) {
            this.items = items;
            return this;
        }

        public TestUser build(){
            return new TestUser(id, name, age, items);
        }
    }
}

先定义了4个私有final属性,然后只给他们提供get方法。不允许他们被set值,这就可以避免对象被创建之后值再次被修改的问题。

然后我们给他提供一个全参私有构造器,全参是为了给final属性初始化时赋值。私有是避免了该类被直接实例化。

我们只允许该类使用其内部类进行实例化操作。所以我们再给他提供一个builder方法,新建一个内部类testUserBuilder。

testUserBuilder类含有和testUser相同类型的属性。并且不能是final,使其在初始化之后允许我们再次给属性赋值。

然后我们提供对应属性的复制方法,例如:

        public testUserBuilder id(int id){
            this.id = id;
            return this;
        }

我们将传入的参数值赋值内部类的属性。最后我们使用build方法,返回TestUser的一个实例。

然后我们测试一下:

        TestUser wm = TestUser.builder().id(1).name("wm").age(10).items(list).build();
        System.out.println(wm.toString());
        System.out.println(wm.getId());
        System.out.println(wm.getName());
        System.out.println(wm.getAge());
        System.out.println(wm.getItems());

先调用TestUser的静态方法builder,生成一个TestUserBuilder对象实例,然后调用赋值方法赋值。最后调用build方法返回TestUser对象实例。

测试结果:

TestUser{id=1, name='wm', age=10, items=[aa, bb]}
1
wm
10
[aa, bb]

其实还有一个更简便的犯法实现建造者模式,就是使用插件lombok。

我们刚才上面手写的建造者模式几个重点是:1,构建器;2,私有全参构造器;3,get方法

那么我们可以使用lombok提供的注解实现。例如:

@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@ToString(exclude = {"age"})
@Getter
public class TestUser {

    private final int id;
    private final String name;
    private final int age;
    private final List<String> items;

}

我们代码简洁了很多,只需要写我们需要的属性即可。编译过后,我们看一下class文件:

public class TestUser {
    private final int id;
    private final String name;
    private final int age;
    private final List<String> items;

    public static TestUser.TestUserBuilder builder() {
        return new TestUser.TestUserBuilder();
    }

    private TestUser(final int id, final String name, final int age, final List<String> items) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.items = items;
    }

    public String toString() {
        return "TestUser(id=" + this.getId() + ", name=" + this.getName() + ", items=" + this.getItems() + ")";
    }

    public int getId() {
        return this.id;
    }

    public String getName() {
        return this.name;
    }

    public int getAge() {
        return this.age;
    }

    public List<String> getItems() {
        return this.items;
    }

    public static class TestUserBuilder {
        private int id;
        private String name;
        private int age;
        private List<String> items;

        TestUserBuilder() {
        }

        public TestUser.TestUserBuilder id(final int id) {
            this.id = id;
            return this;
        }

        public TestUser.TestUserBuilder name(final String name) {
            this.name = name;
            return this;
        }

        public TestUser.TestUserBuilder age(final int age) {
            this.age = age;
            return this;
        }

        public TestUser.TestUserBuilder items(final List<String> items) {
            this.items = items;
            return this;
        }

        public TestUser build() {
            return new TestUser(this.id, this.name, this.age, this.items);
        }

        public String toString() {
            return "TestUser.TestUserBuilder(id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", items=" + this.items + ")";
        }
    }
}

可以看出来,跟我们写的没什么太大差别。

 

这是一种不变模式结合了建造者模式的方法,尤其适合组装之后即最后的结果无需改变并且属性爆炸;比如长报文或者持久化时javabean的最后组装。

其实还可以根据自己的需求进行改变。比如你的值需要经常set改变,那么其实可以放开final并提供set方法。这就要根据需求来看了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值