创建Java对象时,对于可为空的属性,创建对象的时候有3种模式:重叠构造器模式、JavaBeans模式、Builder模式(推荐)、Stream模式(推荐)。


                                                            重叠构造器模式

     该模式使用多个构造器创建Java对象。
     该写法符合Java的标准惯例,但是随着参数的越来越多,代码变得越来越难写。而且该方式灵活性低,可读性较差,客户端想要知道哪些值的具体含义,还需要仔细数参数,而且还容易写错参数的位置。 
package effectiveJava.builder;

public class NutritionFactsMultiContr {
//食物尺寸
private int servingSize;
//食物数量
private int servings;
//热量(卡路里)
private int calories;
//脂肪含量
private int fat;
//食用盐(钠)含量
private int sodium;
//糖类含量
private int carbohydrate; public NutritionFactsMultiContr(int servingSize, int servings) {
this(servingSize,servings,0);
} public NutritionFactsMultiContr(int servingSize, int servings, int calories) {
this(servingSize,servings,calories,0);
} public NutritionFactsMultiContr(int servingSize, int servings, int calories, int fat) {
this(servingSize,servings,calories,fat,0);
} public NutritionFactsMultiContr(int servingSize, int servings, int calories, int fat, int sodium) {
this(servingSize,servings,calories,fat,sodium,0);
} public NutritionFactsMultiContr(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = carbohydrate;
} public static void main(String[] args) {
NutritionFactsMultiContr nutritionFacts = new NutritionFactsMultiContr(1,2,3,4,5,6);
} }

  


                                                    JavaBeans模式

     
      该模式通过调用一个无参构造器来创建对象,并使用setter方法来设置参数值。
      该模式弥补了重叠构造器模式的不足,而且创造实例很容易,代码的可读性也高。但是JavaBeans模式将构造过程分到几个步骤中,在构造过程中JavaBean可能处于不一致的状态,导致一些未知的错误。同时,JavaBeans模式阻止了把类做成不可变的可能。
package effectiveJava.builder;
//营养成分
public class NutritionFactsSetter { //食物尺寸
private int servingSize;
//食物数量
private int servings;
//热量(卡路里)
private int calories;
//脂肪含量
private int fat;
//食用盐(钠)含量
private int sodium;
//糖类含量
private int carbohydrate; public void setServingSize(int servingSize) {
this.servingSize = servingSize;
} public void setServings(int servings) {
this.servings = servings;
} public void setCalories(int calories) {
this.calories = calories;
} public void setFat(int fat) {
this.fat = fat;
} public void setSodium(int sodium) {
this.sodium = sodium;
} public void setCarbohydrate(int carbohydrate) {
this.carbohydrate = carbohydrate;
} public static void main(String[] args) {
NutritionFactsSetter nutritionFacts = new NutritionFactsSetter();
nutritionFacts.setCalories(1);
nutritionFacts.setCarbohydrate(2);
}
}

  


                                                                       Builder模式

 
    该模式不直接生成想要的对象,而是先创建一个builder对象,再在builder上调用类似setter的方法设置参数值,最后调用无参的build方法来生成所需要的对象。(注意:Builder模式下,想要创建的对象的构造器是私有的,这样创建出来的对象是不可变的)
     该模式既能像重叠构造器模式那样的安全性,也能保证像JavaBeans模式那样的可读性,同时实现了对象的不可变性。但是Builder模式为了创建对象,必须先创建它的构建器,导致代码有点冗余。
     Builder模式模拟了具名的可选参数。
package effectiveJava.builder;
//营养成分
public class NutritionFacts { //食物尺寸
private int servingSize;
//食物数量
private int servings;
//热量(卡路里)
private int calories;
//脂肪含量
private int fat;
//食用盐(钠)含量
private int sodium;
//糖类含量
private int carbohydrate; /**
* NutritionFacts是不可变的,不对外提供构造器
* @param builder
*/
private NutritionFacts(Builder builder) {
this.servingSize = builder.servingSize;
this.servings = builder.servings;
this.calories = builder.calories;
this.fat = builder.fat;
this.sodium = builder.sodium;
this.carbohydrate = builder.carbohydrate;
} public static class Builder {
private int servingSize;
private int servings;
private int calories;
private int fat;
private int sodium;
private int carbohydrate; //必填字段
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
} //可选字段
public Builder calories(int val){
this.calories = val;
return this;
} public Builder fat(int val){
this.fat = val;
return this;
} public Builder sodium(int val){
this.sodium = val;
return this;
} public Builder carbohydrate(int val){
this.carbohydrate = val;
return this;
} public NutritionFacts build() {
return new NutritionFacts(this);
}
} public static void main(String[] args) {
NutritionFacts facts = new NutritionFacts.Builder(1, 2).calories(3).fat(4).build();
}
}

  


                                                                    Stream模式

   
    Java8中引入了一种新特性Stream,这让编码变得更加简单易读(其实,该思想在以前的JDK版本中也有使用,例如:StringBuilder、StringBuffer)。在对象的创建过程中,我们也可以使用Stream思想。
    Stream模式就是将setter方法的返回值变为对象本身,这样就可以连续调用setter方法。
package effectiveJava.builder;

public class NutritionFactsStream {
//食物尺寸
private int servingSize;
//食物数量
private int servings;
//热量(卡路里)
private int calories;
//脂肪含量
private int fat;
//食用盐(钠)含量
private int sodium;
//糖类含量
private int carbohydrate; public NutritionFactsStream() {
} public int getServingSize() {
return servingSize;
} public NutritionFactsStream setServingSize(int servingSize) {
this.servingSize = servingSize;
return this;
} public int getServings() {
return servings;
} public NutritionFactsStream setServings(int servings) {
this.servings = servings;
return this;
} public int getCalories() {
return calories;
} public NutritionFactsStream setCalories(int calories) {
this.calories = calories;
return this;
} public int getFat() {
return fat;
} public NutritionFactsStream setFat(int fat) {
this.fat = fat;
return this;
} public int getSodium() {
return sodium;
} public NutritionFactsStream setSodium(int sodium) {
this.sodium = sodium;
return this;
} public int getCarbohydrate() {
return carbohydrate;
} public NutritionFactsStream setCarbohydrate(int carbohydrate) {
this.carbohydrate = carbohydrate;
return this;
} public static void main(String[] args) {
NutritionFactsStream nutritionFacts = new NutritionFactsStream().setServings(1).setServings(2);
}
}

 

此外,创建对象的模式还有很多,比如:工厂模式、单例模式等,不是本文讨论的重点,有兴趣的可以自己研究一下。

参考资料:

  • Joshua Bloch 《Effective Java》
 

Java对象创建模式的更多相关文章

  1. 设计模式---对象创建模式之原型模式(prototype)

    一:概念 原型模式(Prototype Pattern) 实际上就是动态抽取当前对象运行时的状态 Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例.使用Protot ...

  2. 深入理解JavaScript系列(48):对象创建模式(下篇)

    介绍 本篇主要是介绍创建对象方面的模式的下篇,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码. 模式6:函数语法糖 函数语法糖是为一个对象快速添加方法(函数)的扩展,这个主要是利用pro ...

  3. 深入学习Java对象创建的过程:类的初始化与实例化

    在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类构造器完 ...

  4. 《JavaScript 模式》读书笔记(5)— 对象创建模式4

    我们学完了大部分对象创建模式相关的内容,下面还有一些小而精的部分. 七.对象常量 JavaScript中没有常量的概念,虽然许多现代的编程环境可能为您提供了用以创建常量的const语句.作为一种变通方 ...

  5. 《JavaScript模式》第5章 对象创建模式

    @by Ruth92(转载请注明出处) 第5章:对象创建模式 JavaScript 是一种简洁明了的语言,并没有其他语言中经常使用的一些特殊语法特征,如 命名空间.模块.包.私有属性 以及 静态成员 ...

  6. 《Javascript模式》之对象创建模式读书笔记

    引言: 在javascript中创建对象是很容易的,可以使用对象字面量或者构造函数或者object.creat.在接下来的介绍中,我们将越过这些方法去寻求一些其他的对象创建模式. 我们知道js是一种简 ...

  7. 设计模式---对象创建模式之工厂方法模式(Factory Method)

    前提:“对象创建”模式 通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式(表现最为突出) 工 ...

  8. C++设计模式 之 “对象创建”模式:Factory Method、Abstract Factory、Prototype、Builder

    part 0 “对象创建”模式 通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式 Fact ...

  9. 深入理解JavaScript系列(47):对象创建模式(上篇)

    介绍 本篇主要是介绍创建对象方面的模式,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码. 模式1:命名空间(namespace) 命名空间可以减少全局命名所需的数量,避免命名冲突或过度. ...

随机推荐

  1. phpmyadmin系列渗透思路连载(一)

    当拿到phpmyadin的站点后,我一般会尝试一下几种攻击手法: 1.通过弱口令进入后台,尝试into outfile写入一句话 条件:(1)有写的权限    (2)知道web绝对路径    (3)w ...

  2. jmeter跨线程组传值和jmeter跨线程组调用

    Jmeter的线程组之间是独立的,用Jmeter做接口测试或者是性能测试时,经常会涉及到多个线程组.那么如何将A线程组返回的变量信息提取后,传递给B,C线程组使用呢?这里以已登录接口返回的access ...

  3. WeChair Plus版项目介绍

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 团队名称 WeChair 这个作业要求在哪里 团队作业第一次:团队作业第一次(2) 这个作业的目标 项目介绍,项目修改 作业正文 ...

  4. Beta冲刺<9/10>

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺--第九天(05.27) 作业正文 如下 其他参考文献 ... B ...

  5. PHP控制阿里云短信API接口实现短信群发功能

    阿里云短信支持先使用后支付的原则,价格为4分半1条. 通过SDK可以与网站功能的绑定,实现响应的短信发送功能 现已统一合并升级为:消息服务. 消息服务 阿里云消息服务(Message Service, ...

  6. 个人认为目前比较好用的ECMAScript(16-20)新特性

    ECMAScript(16.17.18.19)新特性 Array.prototype.includes includes 是数组上的简单实例方法,可以轻松查找到数组中是否包含指定内容(包括NaN) 返 ...

  7. 小师妹学JVM之:java的字节码byte code简介

    目录 简介 Byte Code的作用 查看Byte Code字节码 java Byte Code是怎么工作的 总结 简介 Byte Code也叫做字节码,是连接java源代码和JVM的桥梁,源代码编译 ...

  8. 为什么 char c = 'A';c += 32; 结果输出的是 'a'?

    首先 char 类型的数据只要参与运行会先转换为 int 类型数值(在 ASCII 编码表中 'A' 对应十进制的 65),那么 'A' 转换为 int 为 65,65 + 32 = 97,+= 包含 ...

  9. 如何在使用spring boot的时候,去掉使用tomcat

    在spring boot中引入spring-boot-starter-web依赖的时候,不想使用spring boot提供的tomcat怎么办呢? 如下配置则可以解决问题: <dependenc ...

  10. DOM对象增删元素

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...