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 相关文章推荐
javascript调试说明
Jun 07 Javascript
javascript工具库代码
Mar 29 Javascript
js window.print实现打印特定控件或内容
Sep 16 Javascript
javascript操作table(insertRow,deleteRow,insertCell,deleteCell方法详解)
Dec 16 Javascript
js打开windows上的可执行文件示例
May 27 Javascript
JavaScript显示当前文档最后修改日期的方法
Mar 19 Javascript
JS获取图片lowsrc属性的方法
Apr 01 Javascript
Javascript中作用域的详细介绍
Oct 06 Javascript
jQuery实现百度登录框的动态切换效果
Apr 21 jQuery
快速解决select2在bootstrap模态框中下拉框隐藏的问题
Aug 10 Javascript
vue中使用vee-validator完成表单校验方案
Nov 01 Javascript
原生js实现移动小球(碰撞检测)
Dec 17 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 header()函数使用详细(301、404等错误设置)
2013/04/17 PHP
php将HTML表格每行每列转为数组实现采集表格数据的方法
2015/04/03 PHP
Node.js中的缓冲与流模块详细介绍
2015/02/11 Javascript
Javascript基于对象三大特性(封装性、继承性、多态性)
2016/01/04 Javascript
Javascript闭包与函数柯里化浅析
2016/06/22 Javascript
如何用JS判断两个数字的大小
2016/07/21 Javascript
Angular 4依赖注入学习教程之ValueProvider的使用(七)
2017/06/04 Javascript
JS实现的加减乘除四则运算计算器示例
2017/08/09 Javascript
原生js实现仿window10系统日历效果的实例
2017/10/31 Javascript
微信小程序模板和模块化用法实例分析
2017/11/28 Javascript
jquery中done和then的区别(详解)
2017/12/19 jQuery
JavaScript静态作用域和动态作用域实例详解
2019/06/17 Javascript
vue-week-picker实现支持按周切换的日历
2019/06/26 Javascript
JS async 函数的含义和用法实例总结
2020/04/08 Javascript
[01:44]剑指西雅图 展望TI之CIS战队专访
2014/06/25 DOTA
[04:48]DOTA2上海特锦赛小组赛第三日 TOP10精彩集锦
2016/02/28 DOTA
[36:05]DOTA2亚洲邀请赛 3.31 小组赛 A组 Liquid vs Optic
2018/04/01 DOTA
Python 字典(Dictionary)操作详解
2014/03/11 Python
Python中使用PIPE操作Linux管道
2015/02/04 Python
Python简单删除列表中相同元素的方法示例
2017/06/12 Python
Python入门之后再看点什么好?
2018/03/05 Python
python 与服务器的共享文件夹交互方法
2018/12/27 Python
python 中如何获取列表的索引
2019/07/02 Python
numpy.transpose()实现数组的转置例子
2019/12/02 Python
Sunglasses Shop荷兰站:英国最大的太阳镜独立在线零售商和供应商
2017/01/08 全球购物
意大利制造的西装、衬衫和针对男士量身定制的服装:Lanieri
2018/04/08 全球购物
马德里著名的运动鞋商店:NOIRFONCE
2019/04/12 全球购物
卫校中专生个人自我评价
2013/09/19 职场文书
查环查孕证明
2014/01/10 职场文书
不服从上级领导安排的检讨书
2014/09/14 职场文书
四风问题个人自查剖析材料思想汇报
2014/09/21 职场文书
2015元旦晚会主持词(开场白+结束语)
2014/12/14 职场文书
武当山导游词
2015/02/03 职场文书
焦裕禄观后感
2015/06/03 职场文书
信用卡工资证明范本
2015/06/19 职场文书
《杜鹃的婚约》OP主题曲「凸凹」无字幕影像公开
2022/04/08 日漫