`
guitar427
  • 浏览: 4731 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

第2条--遇到多个构造器参数时考虑用构建器

 
阅读更多

这条其实没什么好说的,每个程序员都遇到过参数大爆炸的情况,面对大量的可选参数,怎么办?
直接上例子。考虑用一个类表示食品外包装的营养成分标签。这些标签中的有几个域是必须的:每份的分量,每罐的含量以及每份的卡路里,还有超过20个的可选域:总脂肪量,饱和脂肪量,转化脂肪,胆固醇等等,大多数产品在某几个域中都会有非零的值。

Public class NutritionFacts {
    private final int servingSize;//ml required
    private final int serings;// per container required
    private final int calories;//optional
    private final int fat;//g optional
    private final int sodium;//mg optional
    private final int carbonhydrate;//g optional
    public NutritionFacts(int servingSize,int serings){
        this(servingSize,servings,0);
    }
     
    public NutritionFacts(int servingSize,int serings,int calories){
        this(servingSize,serings,calories,0);
    }
     
    public NutritionFacts(int servingSize,int serings,int calories,fat){
        this(servingSize,serings,calories,fat,0);
    }
     
    public NutritionFacts(int servingSize,int serings,int calories,fat,sodium){
        this(servingSize,serings,calories,fat,sodium,0);
    }
     
    public NutritionFacts(int servingSize,int serings,int calories,fat,sodium,carbonhydrate){
        this.servingSize = servingSize;
        this.serings = servings;
        this.calories = calories;
        this.fat = fat;
        this.sodium = sodium;
        this.carbonhydrate = carbonhydrate;
    }
}

这种方式是最常见的,缺点也是显而易见的,代码的可读性非常差,而且非常容易出错。
另外一种常见的方式就是JavaBean的方式,先创建实例,再通过set方法初始化,这种方式的缺点也很明显,破坏了创建对象操作的原子性,在构造过程中对象可能处于不一致的状态。
好了,来看一个两全其美的办法吧:

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 carbonhydrate;
 
    public static class Builder {
        private final int servingSize;
        private final int servings;
 
        private int calories = 0;
        private int fat = 0;
        private int sodium = 0;
        private int carbonhydrate = 0;
         
        public Builder(int servingSize,int serving){
            this.servingSize = servingSize;
            this.servings = serving;
        }
         
        public Builder calories(int val){
            this.calories = val;
            return this;
        }
         
        public Builder fat(int val){
            this.fat = val;
            return this;
        }
         
        public Builder carbonhyate(int val){
            this.carbonhydrate = val;
            return this;
        }
         
        public Builder sodium(int val){
            this.sodium = 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;
        carbonhydrate = builder.carbonhydrate;
    }
     
    public static void main(String[] args) {
        NutritionFacts cocacola = new NutritionFacts.Builder(240,80).calories(100).sodium(35).carbonhyate(27).build();
    }
}

 怎么样,是不是两个缺点都避免了,安全性和可读性都很好,当然Builder模式也有它自身的不足,创建构建器会产生一定的开销,对性能要求非常严格的情况下就不一定是最完美的解决方案了。

分享到:
评论
1 楼 iamhere2012 2013-05-06  
呃,暂时持保留意见

相关推荐

    《C++20设计模式》学习笔记-第2章构造器模式学习代码

    第2章着重讲解了构造器模式,这是一种创建型设计模式,它关注的是对象的初始化过程。下面将详细阐述构造器模式的相关知识点,并结合提供的文件名来推测可能的学习内容。 首先,让我们理解构造器模式的基本概念。在...

    词法分析器构造器

    在构建词法分析器时,我们需要考虑以下关键概念和步骤: 1. **词法规则**:定义每个标记的模式,例如,关键字“if”,数字模式,标识符等。 2. **状态转换**:通过DFA,根据当前读取的字符决定词法分析器应进入的下...

    Laravel开发-former 强大的表单构造器

    在 Laravel 中,开发者可以利用其丰富的工具和库来提高开发效率,而 "Former" 正是这样一个专为 Laravel 设计的表单构造器。 Former 是一款强大的第三方库,它的主要目标是帮助 Laravel 开发者快速、方便地创建和...

    Effective-Java读书笔记(上)

    **遇到多个构造器参数时的考虑**: - **重叠构造器模式**:这种模式下,每个构造器提供比前一个多一个参数,但是这种模式会导致构造器过多,增加复杂度。 - **JavaBeans模式**:虽然使用无参构造器并结合setter方法...

    桂浩 解释器构造实验2

    解释器的构造涉及到多个关键步骤,包括词法分析、语法分析、语义分析和代码生成。下面我们将详细探讨这些步骤以及它们在实验中的重要性。 1. **词法分析**:这是解释器的第一步,它将源代码分解成一系列称为“标记...

    编译原理----------语法分析器-----C语言

    语法分析器是编译器的第二阶段,其主要任务是从词法分析器(也称为扫描器)生成的标记流中构建抽象语法树(AST)。这个过程依据的是源代码的语法规则,通常由一套形式化的文法定义,如上下文无关文法(Context-Free ...

    编译原理词法分析器的构造

    词法分析器的构造是编译器设计与实现的重要组成部分,涉及到了状态转移、正则表达式等多个概念。 1. **词法分析器的作用** 词法分析器的作用是将源代码中的字符流转化为符号流,这个过程包括识别关键字、标识符、...

    【IT十八掌徐培成】Java基础第04天-02.OOP概念-定义类-创建对象.zip

    - 可以有多个构造器,通过不同的参数实现不同方式的初始化。 7. **this关键字**: - `this`关键字引用当前对象实例,常用于区分成员变量和局部变量,以及在构造器中调用其他构造器。 8. **final关键字**: - `...

    新版Android开发教程.rar

    � A ndroid 在设计初期就考虑了与现其有业务的融合,改变以往从计算机为主改成从手机使用为导向。新 生应用如:G oogle 地图及其衍生应用、 GMail 、 GTalk 等。 � GPS 卫星导航功能,手机照相, MP3 ,蓝芽等均...

    C#教程----快速入门

    #### 第二章:Windows编程的基础知识 - **窗口**(第55页) - Windows应用程序的核心组成部分之一。 - **Windows的消息系统** - **消息驱动(事件驱动)** - 应用程序响应用户的输入和其他事件。 - **事件队列...

    数据挖掘实战第2章用scikit-learn估计器分类

    在"数据挖掘实战第2章用scikit-learn估计器分类"中,我们将会深入探讨如何使用scikit-learn进行有效的分类任务。 首先,分类是数据挖掘中的核心任务之一,它旨在根据输入特征将数据点分配到预定义的类别中。scikit-...

    Protege构建本体笔记

    ### Protege构建本体知识点详解 #### 一、概述 Protege是一款广泛使用的开源本体编辑工具,它能够帮助用户构建、管理和编辑基于OWL(Web Ontology Language)的本体。通过Protege,我们可以定义实体之间的关系,...

    《Delphi高级辅助工具精解》PDF版

    8-4-10 在ModelMaker中改进控件 8-4-11 在ModelMaker中继续编辑你的代码 8-4-12 重载构造器Create 8-4-13 实现Create,非用户节代码 8-4-14 即时代码生成 8-4-15 文档化你的控件8-4-16 创建一个帮助文件 8-4-17 在图...

    this关键字共2页.pdf.zip

    - "this"在构造器中可以用来调用其他构造器,但必须作为其第一条语句。 5. **this在实际编程中的应用**: - 在方法重载中,"this"可以帮助避免混淆,确保正确调用实例方法。 - 在构建复杂对象时,"this"可以简化...

    《Java面向对象程序设计(第2版)》课件

    第二版的《Java面向对象程序设计》课件旨在深入浅出地介绍这一关键概念,帮助学习者掌握Java语言的基础以及面向对象编程的核心思想。下面将详细阐述Java面向对象编程的基本概念、特性及其在实际开发中的应用。 1. ...

    线性系统理论-第五章:2观测器.ppt

    状态观测器的研究还包括其维数、结构条件、代数等价等多个方面,这些都是保证系统性能和稳定性的关键因素。通过深入学习和掌握这些理论,工程师能够更好地设计和实现复杂控制系统的状态反馈控制。

    编译原理及实践手工构造词法分析器

    本项目“编译原理及实践手工构造词法分析器”聚焦于手动构建词法分析器这一核心技能,旨在帮助学习者深入理解编译器的工作机制,并通过实践提升对这一领域的掌握。 词法分析器,也被称为扫描器或词法分析程序,是...

    二---十进制的语法分析及语义分析程序设计(LR)

    这个文法定义了一个Number由一个或多个Digit组成,而Digit只能是0或1。类似地,可以为十进制数字建立一个文法。 接下来是语义分析阶段,这个阶段关注的是程序的意义而非结构。在“二---十进制”转换中,语义分析器...

Global site tag (gtag.js) - Google Analytics