高效编码-Builder构建器

在《代码整洁之道》中,方法参数是禁止超过3个的,《代码整洁之道》提倡把超过3个参数的封装到类中.

我们一般在构造一个javaBean 对象时,无非以下几种写法:
1. 采用Javabean 的写法,写一堆属性的setter方法,通过生成对象,让后调用setter方法给属性赋值

/**
 * @author Tonfu.Chia
 */
public class Person {

    private  int id;

    private  String name;

    private  int age;

    private  String sex;

    private  String phone;

    private  String address;

    private  String desc;

    public Person() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}
  1. 各种构造函数 有参 无参
/**
 * @author Tonfu.Chia
 */
public class Person {

    private  int id;

    private  String name;

    private  int age;

    private  String sex;

    private  String phone;

    private  String address;

    private  String desc;

    public Person() {
    }

    public Person(int id, String name, int age, String sex, String phone, String address, String desc) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.phone = phone;
        this.address = address;
        this.desc = desc;
    }

    public Person(int id, String name, int age, String sex) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
}
  1. 重叠构造器模式
/**
 * @author Tonfu.Chia
 */
public class Person {
    //必要参数
    private final int id;
    private final String name;
    //可选参数
    private final int age;
    private final String sex;
    private final String phone;
    private final String address;
    private final String desc;

    public Person(int id, String name) {
        this(id, name, 0);
    }

    public Person(int id, String name, int age) {
        this(id, name, age, "");
    }

    public Person(int id, String name, int age, String sex) {
        this(id, name, age, sex, "");
    }

    public Person(int id, String name, int age, String sex, String phone) {
        this(id, name, age, sex, phone, "");
    }

    public Person(int id, String name, int age, String sex, String phone, String address) {
        this(id, name, age, sex, phone, address, "");
    }

    public Person(int id, String name, int age, String sex, String phone, String address, String desc) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.phone = phone;
        this.address = address;
        this.desc = desc;
    }
}

比较

构造方式优点缺点
JavaBean创建灵活,代码易可读构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。
构造函数每种初始化都可以对应单独方法属性过多的话会让构造函数十分臃肿,而且不能灵活的选择只设置某些参数,添加参数需要添加对应构造方法。
重叠构造器比构造函数灵活,参数少时可以使用如果参数比较多时,类里面会出现一堆构造方法,并且阅读困难,很容易就把两个属性参数写颠倒位置了,编译不会出错,但运行就会出错了

更高效的构造方式–构建器

在《Effective Java第2版》第二章创建和销毁对象 中有提到,

遇到多个构造器参数时要考虑使用构建器(Builder模式)

使用Builder模式的步骤:
1. 不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个build对象。
2. 然后让客户端在build对象上调用类似的setter方法来设置每个相关的可选参数,
3. 最后,客户端调用无参的build方法来生成不可变的对象。这个builder是它构建的静态成员类。

package com.ampmind.common.model.swagger;

/**
 * @author Tonfu.Chia
 */
public class Person {

    //必要参数
    private final int id;

    private final String name;

    //可选参数
    private final int age;

    private final String sex;

    private final String phone;

    private final String address;

    private final String desc;

    private Person(Builder builder) {
        this.id = builder.id;
        this.name = builder.name;
        this.age = builder.age;
        this.sex = builder.sex;
        this.phone = builder.phone;
        this.address = builder.address;
        this.desc = builder.desc;
    }

    public static class Builder {

        //必要参数
        private final int id;

        private final String name;

        //可选参数
        private int age;

        private String sex;

        private String phone;

        private String address;

        private String desc;

        public Builder(int id, String name) {
            this.id = id;
            this.name = name;
        }

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

        public Builder sex(String val) {
            this.sex = val;
            return this;
        }

        public Builder phone(String val) {
            this.phone = val;
            return this;
        }

        public Builder address(String val) {
            this.address = val;
            return this;
        }

        public Builder desc(String val) {
            this.desc = val;
            return this;
        }

        public Person build() {
            return new Person(this);
        }
    }
}

Person是不可变的,所有的默认参数值都单独放在一个地方。builder的setter方法返回builder本身。以便可以把连接起来。下面是客户端使用代码:

public class Test {

    public static void main(String[] args) {
        Person person = new Person.Builder(1, "张三")
                .age(18).sex("男").desc("测试使用Builder模式").build();
        System.out.println(person.toString());
    }
}

Lombok - @Builder

/**
 * @author Tonfu.Chia
 */
@Builder
@Getter
@RequiredArgsConstructor
public class Person {

    //必要参数
    @NonNull
    private final int id;

    @NonNull
    private final String name;

    //可选参数
    private final int age;

    private final String sex;

    private final String phone;

    private final String address;

    private final String desc;

}

使用如下 :

Person person= Person.builder().id(1).name("张三").age(22).sex("男").build();

实际使用情况

  1. 是不是可以不用Setter,而使用Builder,哪些地方会遇到问题?
  2. Mybatis 可以给没有set的bean赋值?
  3. lombok 不支持Builder设置有参构造器?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值