《Effective Java》(第2版)中第二条中提到:遇到多个构造器参数时要考虑用构建器。在复习static关键字和内部类时回头看了一下,这才明白了为什么要用静态内部类来做处理,这里记录一下。

先看再看一下《Effective Java》书中的例子,例子中是用一个类表示包装食品外面显示的营养成分标签。这些标签中有几个是必需的:每份的含量、每罐的含量以及每份的卡路里,还有超过20个可选域:总脂肪量、饱和脂肪量、转化脂肪、胆固醇、钠等。如果用一般的处理方式,直接把这些参数在构造器中初始化的话,有两个缺点:
1、没法体现营养成分的必需和非必需属性
2、参数太多,这样在实例化传参数的时候其实比较难区分的。因为他们几乎都是int型变量,而且即使传递错了也不会有任何提醒。
基于上面的问题,书中转而使用Builder模式,当然,Builder模式能解决上面的问题,那么也间接说明了Builder模式的优点。(1、区分必传和选传参数2、比较明确的表示出参数的含义)
这里直接把书中代码搬过来:
 public class NutritionFacts {
private final int servingSize;//份容量
private final int servings;//份
private final int calories;//卡路里
private final int fat;//脂肪
private final int sodium;//钠
private final int carbohydrate;//糖类
public static class Builder{
private final int servingSize;//份容量
private final int servings;//份
//必要参数
public Builder(int servingSize,int servings){
this.servingSize=servingSize;
this.servings=servings;
}
private int calories = ;
private int fat = ;
private int sodium = ;
private int carbohydrate = ;
public Builder calories(int val){
calories = val;
return this;
}
public Builder fat(int val){
fat = val;
return this;
}
public Builder sodium(int val){
sodium = val;
return this;
}
public Builder carbohydrate(int val){
carbohydrate = val;
return this;
}
public NutritionFacts build(){
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder){
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
使用时比较简单,而且比较清晰:
 NutritionFacts cocoCola = new NutritionFacts.Builder(,).calories().carbohydrate().build();
注意点:
1、对于NutritionFacts来说,包含了三部分,final成员变量,私有构造器、静态内部类。final成员变量保证了初始化安全性,即在构造器执行完成之前必须显示对成员变量初始化。这里是在构造函数中传入Builder来对其初始化。
2、构造器为什么要声明为私有的?保证了外部创建实例时只能通过静态内部类的build()方法来实现。
3、为什么是静态内部类?因为构造器是私有的,导致外部只能通过内部类的build()方法来实现。而非静态内部类对象的创建又依赖于外部类对象,即必须有外部类对象来创建(外部类对象.new InnerClassName()),这样就陷入了死循环。而静态内部类不需要依赖于外部类对象,只需要通过 “new OutClassName.InnerClassName()”就可以完成实例化。
4、内部类Builder通过final关键字来区分必需参数和非必需参数。通过builder()方法完成外部类实例化。这里利用内部类可以访问外部私有元素的特性。
5、总的来看,就是外部类通过静态内部类完成了自己成员变量的初始化。
 参考书籍:
《Effective Java》

Builder模式的思考(Effective Java)的更多相关文章

  1. Java设计模式(3)建造者模式(Builder模式)

    Builder模式定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构 ...

  2. Builder模式详解及其在Android开发中的应用

    一.引言 在Android开发中,采用Builder模式的代码随处可见,比如说Android系统对话框AlertDialog的使用或者是Android中的通知栏(Notification)的使用,又比 ...

  3. Builder模式的目的是解耦构建过程,为什么要用内部类?

    还没有看过Builder模式的作用,看过一篇介绍Builder模式的文章,这里是关于Builder模式的思考:思考是否有比新建一个内部类更好的方法,首先想到的是 package xyz.n490808 ...

  4. 同事写了一个疯狂的类构造器,我要疯了,Builder 模式都不会么?!

    疯狂的类构造器 最近栈长在做 Code Review 时,发现一段创建对象的方法: Task task = new Task(112, "紧急任务", "处理一下这个任务 ...

  5. 疯狂的类构造器Builder模式,链式调用

    疯狂的类构造器 最近栈长在做 Code Review 时,发现一段创建对象的方法: Task task = new Task(112, "紧急任务", "处理一下这个任务 ...

  6. 解析《Effective Java》之多个构造器、Javabeans模式和Builder模式

    最近看<Effective Java>这本被很多同行称为神作的书,但是这本书很多地方缺少了举例不好懂,下面是关于我对书上知识的理解. 一.<Effective Java>中文版 ...

  7. effective java 3th item2:考虑 builder 模式,当构造器参数过多的时候

    yiaz 读书笔记,翻译于 effective java 3th 英文版,可能有些地方有错误.欢迎指正. 静态工厂方法和构造器都有一个限制:当有许多参数的时候,它们不能很好的扩展. 比如试想下如下场景 ...

  8. Effective Java 第三版——2. 当构造方法参数过多时使用builder模式

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  9. Builder模式在Java中的应用

    在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...

随机推荐

  1. hs_err_pid

    hs_err_pid这种文件,是JVM出现错误时dump下来的.记录了错误发生当时: 1)JVM的状态参数 2)Linux的状态参数 就以下面的文件为例: # # There is insuffici ...

  2. Linux目录结构详解(一)

    Linux目录结构,在逻辑上所有目录只有一个顶点,即/(根目录),是所有目录的起点.根下面类似于一个倒挂着的树的结构. Linux目录按照类别组织: 应用程序 /usr/bin 数据文件,帮助/usr ...

  3. NopCommerce 1. NopCommerce Application_Start启动过程

    这里简单介绍整个启动过程,其他具体的后续讲解 从Application_Start中执行开始,一开始执行EngineContext.Initialize(false); EngineContext 是 ...

  4. win10 uwp 切换主题

    本文主要说如何在UWP切换主题,并且如何制作主题. 一般我们的应用都要有多种颜色,一种是正常的白天颜色,一种是晚上的黑夜颜色,还需要一种辅助的高对比颜色.这是微软建议的,一般应用都要包含的颜色. 我们 ...

  5. 解析 .Net Core 注入 (2) 创建容器

    在上一节的学习中,我们已经知道了通过 IServiceCollection 拓展方法创建 IServiceProvider 默认的是一个类型为 ServiceProvider 对象,并且实际提供创建对 ...

  6. git 一口气带你走完git之旅

    1.git是目前世界上最先进的分布式版本控制系统.svn是集成式版本控制系统,那么问题来了,什么叫分布式管理和集中式管理? 首先,svn 需要有一个中央服务器,协同开发者需要同中央服务器连接,所有的版 ...

  7. [POJ 1410] Intersection(线段与矩形交)

    题目链接:http://poj.org/problem?id=1410 Intersection Time Limit: 1000MS   Memory Limit: 10000K Total Sub ...

  8. eval函数的坑

    开发工作中遇到这样一种情形,需要执行用户输入的php代码串,于是决定使用eval函数.coding大概示例如下: function getStr($str) { return strlen($str) ...

  9. LeetCode 152. Maximum Product Subarray (最大乘积子数组)

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  10. linux学习(五)系统目录结构,ls命令,文件类型,alias

    一.系统目录结构 在我们的根目录下,有这样一些文件夹 /bin /sbin /usr/bin /usr/sbin /sbin一般都是root用户用的 /boot 系统启动相关的,grup就放在这里,这 ...