Java设计中的Builder模式的介绍


Posted in Javascript onMarch 22, 2018

概述

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

使用场景

  • 相同的方法,不同的执行顺序,产生不同的事件结果
  • 多个部件或零件,都可以装配到一个对象中,但产生的运行结果又不相同时
  • 产品类非常复杂,或者产品类中的调用顺序不同产生不同的作用
  • 当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时

下面从一个Person例子进行分析重叠构造器模式、JavaBeans模式、Builder模式的使用。Person类有两个必要参数(id和name),有5个可选参数(age,sex,phone,address和desc)

重叠构造器模式

在这种模式下,你提供第一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,依此类推,最后一个构造器包含所有的可选参数。下面看看其编程实现:

/ * 使用重叠构造器模式
 */
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;
 }
}

从上面的代码中,当你想要创建实例的时候,就利用参数列表最短的构造器,但该列表中包含了要设置的所有参数:

Person person = new Persion(1, "李四", 20, "男", "18800000000", "China", "测试使用重叠构造器模式");

重叠构造器可行,但是当有许多参数的时候,创建使用代码会很难写,并且较难以阅读

JavaBeans模式

采用Javabean 的写法,写一堆属性的setter方法,通过生成对象,让后调用setter方法给属性赋值。

/ * 使用JavaBeans模式
 */
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 void setId(int id) {
 this.id = id;
 }
 public void setName(String name) {
 this.name = name;
 }
 public void setAge(int age) {
 this.age = age;
 }
 public void setSex(String sex) {
 this.sex = sex;
 }
 public void setPhone(String phone) {
 this.phone = phone;
 }
 public void setAddress(String address) {
 this.address = address;
 }
 public void setDesc(String desc) {
 this.desc = desc;
 }

这种模式弥补了重叠构造器模式的不足。创建实例很容易,这样产生的代码读起来也很容易:

Person person = new Person();
person.setId(1);
person.setName("李四");
person.setAge(20);
person.setSex("男");
person.setPhone("18800000000");
person.setAddress("China");
person.setDesc("测试使用JavaBeans模式");

JavaBeans模式因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。类无法仅仅通过检验构造器参数的有效性来保证一致性。

Builder模式

Builder模式既能保证像重叠构造器那样的安全,也能实现JavaBean模式那样的可读性。

/**
 * 使用Builder模式
 */
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本身,以便可以链式调用。下面是客户端使用代码:

Person person = new Person.Builder(1, "张三")
                .age(18).sex("男").desc("测试使用builder模式").build();

Android源码中的Builder模式

  • AlertDialog源码
  • Universal-Image-Loader图片库
  • OkHttp的Request源码

优点:

  • 良好的封装性,使用建造者模式可以使客户端不比知道产品内部组成的细节
  • 建造者独立,容易扩展(可通过抽象———接口,抽象类)

缺点:

  • 会产生多余的Builder对象以及Director对象,消耗内存

总结 :Builder模式通常作为配置类的构建器将配置的构建和表示分离开来,同时也是将配置从目标类中隔离出来,避免过多的setter方法。

Javascript 相关文章推荐
限制复选框的最大可选数
Jul 01 Javascript
javascript (用setTimeout而非setInterval)
Dec 28 Javascript
script不刷新页面的联动前后代码
Sep 18 Javascript
jquery mobile的触控点击事件会多次触发问题的解决方法
May 08 Javascript
Javascript编程中几种继承方式比较分析
Nov 28 Javascript
AngularJS入门心得之directive和controller通信过程
Jan 25 Javascript
jQuery自制提示框tooltip改进版
Aug 01 Javascript
基于BootStrap与jQuery.validate实现表单提交校验功能
Dec 22 Javascript
JS非空验证及邮箱验证的实例
Aug 11 Javascript
JS中的Replace()传入函数时的用法详解
Sep 11 Javascript
Angular ElementRef简介及其使用
Oct 01 Javascript
TS 类型兼容教程示例详解
Sep 23 Javascript
使用vue-route 的 beforeEach 实现导航守卫(路由跳转前验证登录)功能
Mar 22 #Javascript
收集前端面试题之url、href、src
Mar 22 #Javascript
vue 的keep-alive缓存功能的实现
Mar 22 #Javascript
bootstrap中selectpicker下拉框使用方法实例
Mar 22 #Javascript
使用Vue开发动态刷新Echarts组件的教程详解
Mar 22 #Javascript
JavaScript分步实现一个出生日期的正则表达式
Mar 22 #Javascript
vuex 的简单使用
Mar 22 #Javascript
You might like
一些常用的php简单命令代码集锦
2007/09/24 PHP
thinkphp模板的包含与渲染实例分析
2014/11/26 PHP
PHP中开启gzip压缩的2种方法
2015/01/31 PHP
PHP使用mysqldump命令导出数据库
2015/04/14 PHP
CodeIgniter基于Email类发邮件的方法
2016/03/29 PHP
PHP如何将XML转成数组
2016/04/04 PHP
php表单处理操作
2017/11/16 PHP
DHTML 中的绝对定位
2006/11/26 Javascript
ymPrompt的doHandler方法来实现获取子窗口返回值的方法
2010/06/25 Javascript
jQuery getJSON 处理json数据的代码
2010/07/26 Javascript
jquery实现心算练习代码
2010/12/06 Javascript
jQuery仅用3行代码实现的显示与隐藏功能完整实例
2015/10/08 Javascript
基于javascript bootstrap实现生日日期联动选择
2016/04/07 Javascript
基于JS实现数字+字母+中文的混合排序方法
2016/06/06 Javascript
jQuery Plupload上传插件的使用
2017/04/19 jQuery
vue.js全局API之nextTick全面解析
2017/07/07 Javascript
AngularJS实现select的ng-options功能示例
2017/07/12 Javascript
bootstrap paginator分页插件的两种使用方式实例详解
2017/11/14 Javascript
Vue-Access-Control 前端用户权限控制解决方案
2017/12/01 Javascript
Vue中的混入的使用(vue mixins)
2018/06/01 Javascript
HTML+JavaScript实现扫雷小游戏
2019/09/30 Javascript
vue+canvas实现移动端手写签名
2020/05/21 Javascript
Python编程pygame模块实现移动的小车示例代码
2018/01/03 Python
Python使用smtp和pop简单收发邮件完整实例
2018/01/09 Python
基于numpy.random.randn()与rand()的区别详解
2018/04/17 Python
pandas 两列时间相减换算为秒的方法
2018/04/20 Python
python实现大战外星人小游戏实例代码
2019/12/26 Python
Python中bisect的使用方法
2019/12/31 Python
HTML5中的新元素介绍
2008/10/17 HTML / CSS
HTML5跳转小程序wx-open-launch-weapp的示例代码
2020/07/16 HTML / CSS
印尼披萨外送专家:Domino’s Pizza印尼
2017/12/28 全球购物
大学生未来职业生涯规划书
2014/02/15 职场文书
上班玩手机检讨书
2014/02/17 职场文书
师范教师专业大学生职业生涯规划范文
2014/03/02 职场文书
平安建设实施方案
2014/03/19 职场文书
vue项目打包后路由错误的解决方法
2022/04/13 Vue.js