构建者模式(封装一个产品的构造过程)

源码地址 https://github.com/DingMouRen/DesignPattern
定义

构建者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

使用场景
  • 相同的方法,不同的执行顺序,产生不同的事件结果。
  • 当初始化一个对象,需要的参数比较多时,并且有一些参数都具有默认值。
举个栗子

我们要创建一个合同对象,一个合同对象需要很多的参数,这属于一个复杂对象的构建。

/**
 * Created by dingmouren on 2017/8/16.
 * email:[email protected]
 * 保险合同对象
 */

public class InsuranceContract {
    private String contractid;
    private String personName;
    private String companyName;
    private long beginDate;
    private long endDate;
    private String otherData;

    /**
     * 只让Builder能够创建对象
     *
     * @param builder
     */
    private InsuranceContract(ConcreteBuilder builder) {
        this.contractid = builder.getContractid();
        this.personName = builder.getPersonName();
        this.companyName = builder.getCompanyName();
        this.beginDate = builder.getBeginDate();
        this.endDate = builder.getEndDate();
        this.otherData = builder.getOtherData();
    }

    /**
     * 保险合同对象的其他操作
     */
    public void showInfo() {
        System.out.println("保险合同的详细信息:......");
    }

    /**
     * Created by dingmouren on 2017/8/16.
     * email:[email protected]
     * 构建保险合同对象的构建器
     */
    public static class ConcreteBuilder {
        private String contractid;
        private String personName;
        private String companyName;
        private long beginDate;
        private long endDate;
        private String otherData;

        /**
         * 构造函数总传入必须要有的参数
         *
         * @param contractid 保险合同编号
         * @param beginDate  保险合同开始日期
         * @param endDate    保险失效日期
         */
        public ConcreteBuilder(String contractid, long beginDate, long endDate) {
            this.contractid = contractid;
            this.beginDate = beginDate;
            this.endDate = endDate;
        }



        //下面是选填数据的设置,都返回构建器对象
        public ConcreteBuilder setPersonName(String personName) {
            this.personName = personName;
            return this;
        }

        public ConcreteBuilder setCompanyName(String companyName) {
            this.companyName = companyName;
            return this;
        }

        public ConcreteBuilder setOtherData(String otherData) {
            this.otherData = otherData;
            return this;
        }

        /**
         * 构建真正的对象并返回
         *
         * @return 保险合同对象
         */
        public InsuranceContract build() {

            //进行整体数据校验
            if (contractid == null || contractid.trim().length() == 0) throw new IllegalArgumentException("合同编号不能为空");

            //这是设计到两个数据的约束关系,在build方法中校验比较合适
            boolean signPerson = personName != null && personName.trim().length() > 0;
            boolean signCompany = companyName != null && companyName.trim().length() > 0;

            if (signCompany && signPerson) throw new IllegalArgumentException("一份合同不能同时与人和公司签订");
            if (signCompany == false && signPerson == false) throw new IllegalArgumentException("一份合同不能没有签订对象");
            if (beginDate <= 0) throw new IllegalArgumentException("合同必须有保险开始生效日期");
            if (endDate <= 0) throw new IllegalArgumentException("合同必须有保险失效日期");
            if (endDate <= beginDate) throw new IllegalArgumentException("保险失效日期必须大于保险的生效日期");

            return new InsuranceContract(this);
        }

        //下面是提供getter方法供外部访问,注意没有setter方法哦


        public String getContractid() {
            return contractid;
        }

        public String getPersonName() {
            return personName;
        }

        public String getCompanyName() {
            return companyName;
        }

        public long getBeginDate() {
            return beginDate;
        }

        public long getEndDate() {
            return endDate;
        }

        public String getOtherData() {
            return otherData;
        }
    }
}

使用

 public static void main(String[] args) {
        InsuranceContract.ConcreteBuilder builder = new InsuranceContract.ConcreteBuilder("001",1100L,1199L);
        InsuranceContract contract = builder.setCompanyName("太平保险")
                .setPersonName("小明")
                .setOtherData("其他信息")
                .build();
        contract.showInfo();//显示保险合同信息
    }
总结

优点

  • 良好的封装,构建者模式使得客户端不必知道产品内部的组成细节
  • 构建者独立,容易扩展。
    缺点
  • 会产生多余的Builder对象,消耗内存

以上的构建者模式是在Android中常用的,与一般的构建者模式略有不同。

你可能感兴趣的:(构建者模式(封装一个产品的构造过程))