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 showModalDialog 多层模态窗口实现页面提交及刷新的代码
Nov 28 Javascript
javascript tips提示框组件实现代码
Nov 19 Javascript
js 时间函数应用加、减、比较、格式转换的示例代码
Aug 23 Javascript
jQuery实现自定义事件的方法
Apr 17 Javascript
JS模拟酷狗音乐播放器收缩折叠关闭效果代码
Oct 29 Javascript
详解jquery easyui之datagrid使用参考
Dec 05 Javascript
JavaScript常用正则验证函数实例小结【年龄,数字,Email,手机,URL,日期等】
Jan 23 Javascript
JavaScript轻松创建级联函数的方法示例
Feb 10 Javascript
angularJS+requireJS实现controller及directive的按需加载示例
Feb 20 Javascript
浅谈vue中慎用style的scoped属性
Nov 28 Javascript
如何优雅地取消 JavaScript 异步任务
Mar 22 Javascript
使用Vant完成Dialog弹框案例
Nov 11 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详细彻底学习Smarty
2008/03/27 PHP
9个PHP开发常用功能函数小结
2011/07/15 PHP
php获取QQ头像并显示的方法
2014/12/23 PHP
php编译安装php-amq扩展简明教程
2016/06/25 PHP
Laravel给生产环境添加监听事件(SQL日志监听)
2017/06/19 PHP
php微信扫码支付 php公众号支付
2019/03/24 PHP
PHP命名空间定义与用法实例分析
2019/08/14 PHP
一些常用的Javascript函数
2006/12/22 Javascript
jQuery 注意事项 与原因分析
2009/04/24 Javascript
js 完美图片新闻轮转效果,腾讯大粤网首页图片轮转改造而来
2011/11/21 Javascript
js模拟滚动条(横向竖向)
2013/02/22 Javascript
关于删除时的提示处理(确定删除吗)
2013/11/03 Javascript
jQuery中animate用法实例分析
2015/03/09 Javascript
jQuery插件zepto.js简单实现tab切换
2015/06/16 Javascript
JS+CSS实现另类带提示效果的竖向导航菜单
2015/10/15 Javascript
关于微信中a链接无法跳转问题
2016/08/02 Javascript
JavaScript 判断一个对象{}是否为空对象的简单方法
2016/10/09 Javascript
神级程序员JavaScript300行代码搞定汉字转拼音
2017/05/20 Javascript
Vue3.x源码调试的实现方法
2019/10/13 Javascript
如何管理Vue中的缓存页面
2021/02/06 Vue.js
如何使用python爬取csdn博客访问量
2016/02/14 Python
Python中的if、else、elif语句用法简明讲解
2016/03/11 Python
python logging重复记录日志问题的解决方法
2018/07/12 Python
Python单元和文档测试实例详解
2019/04/11 Python
学习python分支结构
2019/05/17 Python
python中property属性的介绍及其应用详解
2019/08/29 Python
Python pygame绘制文字制作滚动文字过程解析
2019/12/12 Python
Pycharm+Python工程,引用子模块的实现
2020/03/09 Python
python urllib和urllib3知识点总结
2021/02/08 Python
C#笔试题集合
2013/06/21 面试题
中药专业大学生医药工作求职信
2013/10/25 职场文书
加强机关作风建设心得体会
2014/10/22 职场文书
2016年大学生党员承诺书
2016/03/24 职场文书
Python的flask接收前台的ajax的post数据和get数据的方法
2021/04/12 Python
浅谈Python魔法方法
2021/06/28 Java/Android
el-table-column 内容不自动换行的解决方法
2022/08/14 Vue.js