`
clearity
  • 浏览: 36962 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用Builders代替构造器创建不可变对象

 
阅读更多

本篇将拿构造器来和使用builder设计模式比较着解释应该如何创建不可变对象

使用此种方式可以使你的代码更具有可读性,首先,让我们来看下如果使用如下的接收三个BigDecimal类型参数的构造器来构建的CashBalance对象是多么的不优雅。然后我们会在看下使用builder模式是怎样让你的代码更简洁的。

 

当下次你在面试中被问及设计模式的时候,你可以拿这个实现来和使用很频繁的工厂模式和单例模式做个比较。这篇文章还设计到其他两个重要的概念(不可变性和线程安全)

 

 

import java.math.BigDecimal;
 
/**
 * 因为不可变,所以是线程安全的对象
 */
public final class CashBalance {
  
 private BigDecimal initialBalance;
 private BigDecimal totCredits;
 private BigDecimal totDebits;
  
 //构造器
 public CashBalance(BigDecimal initialBalance, BigDecimal totCredits, BigDecimal totDebits) {
  this.initialBalance = initialBalance;
  this.totCredits = totCredits;
  this.totDebits = totDebits;
 }
  
 //不可变对象中只提供getter方法,不提供setter方法
 
}

 

 

因此,这段代码哪里不优雅?首先它的构造器需要三个BigDecimal的参数,在使用类的时候对于参数的意义来说不怎么直观,你说不清哪个参数是initialBalance,哪个参数是totCredits,如果你使用下面的方式来调用构造器会更好

 

 

CashBalance bal = new CashBalance(initialBalance:BigDecimal.valueOf(250.00), 
                                  totCredits:BigDecimal.valueOf(250.00), 
          totDebits:BigDecimal.valueOf(250.00));

 

 

很不幸的是,你不能使用上面的语法来写程序,你只能通过下面的方式调用它.

 

 

CashBalance bal = new CashBalance(BigDecimal.valueOf(250.00), 
                                  BigDecimal.valueOf(250.00), 
          BigDecimal.valueOf(250.00));

 

 

通过一个空构造器和三个setter方法来实现代码会更为优雅,但是对象必须是不可变的。下面是拯救你的构造器设计模式的代码。通过定义一个内部类来构造CashBalance对象。

 

 

import java.math.BigDecimal;
 
/**
 * 不可变,所以线程安全
 */
public final class CashBalance {
  
 private BigDecimal initialBalance, totCredits, totDebits;
  
 //构造器
 public CashBalance(CashBalanceBuilder builder) {
  this.initialBalance = builder.initialBalance;
  this.totCredits = builder.totCredits;
  this.totDebits = builder.totDebits;
 }
  
 //构造器模式
 public static class CashBalanceBuilder {
   
  // 有需要构造的对象一致的字段列表
  protected BigDecimal initialBalance, totCredits, totDebits;
 
  //将访问权限设置为包内访问
  void setInitialBalance(BigDecimal initialBalance) {
   this.initialBalance = initialBalance;
  }
 
  void setTotCredits(BigDecimal totCredits) {
   this.totCredits = totCredits;
  }
 
  void setTotDebits(BigDecimal totDebits) {
   this.totDebits = totDebits;
  } 
 }
  
 //只提供setter方法
 
}

 

 

现在,你可以像下面调用一样在类外面构造CashBalance

 

 

public static void main(String[] args) {
 CashBalance.CashBalanceBuilder builder = new CashBalance.CashBalanceBuilder();
 builder.setInitialBalance(BigDecimal.valueOf(250.00));
 builder.setTotCredits(BigDecimal.valueOf(250.00));
 builder.setTotDebits(BigDecimal.valueOf(250.00));
 CashBalance bal = new CashBalance(builder);
}

 

 

上面的代码完成了,但是如果你还有更多的字段,构造的代码就会显得很臃肿。这个可以用下面的方式来改善。

 

下面代码的改进是通过修改void类型的setter方法设值后返回builder自身来实现的

 

import java.math.BigDecimal;
 
/**
 * 不可变线程安全对象
 */
public final class CashBalance {
  
 private BigDecimal initialBalance, totCredits, totDebits;
  
 //构造器
 public CashBalance(CashBalanceBuilder builder) {
  this.initialBalance = builder.initialBalance;
  this.totCredits = builder.totCredits;
  this.totDebits = builder.totDebits;
 }
  
  
 public static class CashBalanceBuilder {
   
  //has same fields as the object it is going to build
  protected BigDecimal initialBalance, totCredits, totDebits;
 
  //define the setters that return itself
  CashBalanceBuilder setInitialBalance(BigDecimal initialBalance) {
   this.initialBalance = initialBalance;
   return this;
  }
 
  CashBalanceBuilder setTotCredits(BigDecimal totCredits) {
   this.totCredits = totCredits;
   return this;
  }
 
  CashBalanceBuilder setTotDebits(BigDecimal totDebits) {
   this.totDebits = totDebits;
   return this;
  } 
 }
  
 
}

 

代码修改带来的优雅是现在可以通过下面的构造方式调用:

 

public static void main(String[] args) {
   CashBalance.CashBalanceBuilder builder = new CashBalance.CashBalanceBuilder()
     .setInitialBalance(BigDecimal.valueOf(250.00))
     .setTotCredits(BigDecimal.valueOf(250.00))
     .setTotDebits(BigDecimal.valueOf(250.00));
   CashBalance bal = new CashBalance(builder);
}

 

因此这些秘诀可以让你在和职场达人的面试中赢得加分

分享到:
评论

相关推荐

    Information Builders公司介绍

    ### Information Builders公司介绍 #### 公司概述 Information Builders(简称IBI或艾比埃)是一家专注于为企业提供商务智能(Business Intelligence, BI)、数据分析及信息管理解决方案的领先供应商。自成立以来...

    java-builders:检查Java对象的构建变体

    属性是非最终的,因此对象是可变的,请参见 IDEA InnerBuilder IDEA InnerBuilder 示例。 优点: 字段仅需指定,所有方法都可以由IDEA生成。 缺点: 你必须使用; 所有样板仍驻留在源代码控制系统中。 Goo

    jbw-builders, 某些基础类的生成器类别.zip

    jbw-builders, 某些基础类的生成器类别 jbw-builderNSURL 和 NSDate的生成器类别。 生成器类别添加了一个基于构造器 Pattern的便捷初始化器,... 不创建自定义构建器对象,而是使用基础 NS*Components 对象中的。By J

    Joshua Bloch 所著《Effective Java 第二版》一书摘要.zip

    使用私有构造函数来强制实现不可实例化5. 避免创建对象6. 消除过时的对象引用7. 避免使用 finalizer3. 所有对象通用的方法8. 覆盖equals时遵守一般约定9.重写equals时务必重写hashCode10. 始终覆盖toString11.明智...

    Information Builders产品列表

    ### Information Builders产品列表详解 #### 一、概述 Information Builders是一家知名的商业智能(BI)解决方案提供商,其产品广泛应用于数据分析、报表制作、数据治理等多个领域。本文将基于给定的产品列表,...

    Builders:使用注释处理器生成流畅的构建器

    ##Overview Builders 是一个,它生成一个 ,然后可用于创建和/或填充对象。 要使用 Builders,只需将添加到您的类路径,并注释您要创建构建器的类以使用注释。 然后构建器将执行以下操作: 默认生成 Builder 类(您...

    Angular-angular-builders.zip

    Angular-angular-builders.zip,angular cli@angular builders的一组自定义生成器,Angularjs于2016年发布,是Angularjs的重写版。它专注于良好的移动开发、模块化和改进的依赖注入。angular的设计目的是全面解决开发...

    前端开源库-Builders

    在前端开发领域,开源库是开发者们不可或缺的工具,它们为快速构建高效、可维护的Web应用提供了便利。"Builders"是一种专注于构建前端资产的开源库,尤其关注CSS、JavaScript和Sprites的创建与管理。本篇文章将深入...

    now-builders:ZEIT团队创建的Official Now Now Builders

    【now-builders】是ZEIT团队创建的一个官方项目,它主要关注的是构建和优化Serverless应用程序。ZEIT是一家专注于云原生开发工具和服务的公司,其Now平台是部署无服务器应用的快速、简单的方式。Now Builders是Now...

    PyPI 官网下载 | aws_lambda_builders-0.8.0-py2-none-any.whl

    Lambda函数可以响应各种事件,如API调用、S3对象更改或数据库事件,从而实现高度可扩展和低成本的计算。 **aws_lambda_builders** `aws_lambda_builders` 是一个Python库,由AWS官方维护,用于构建和打包AWS ...

    PyPI 官网下载 | emmet-builders-0.8.0.tar.gz

    emmet-builders库的具体功能可能包括但不限于创建和解析Emmet的构建规则,处理各种前端模板语言的转换,以及提供API让开发者自定义Emmet的行为。为了更好地理解和利用这个库,开发者应详细阅读其官方文档,了解各个...

    linphone-desktop出现Cmake Error at builders/vpx.cmake:89的几个错误文件解决

    Cmake Error at builders/vpx.cmake:89 Cmake Error at builders/vpx.cmake:88 Cmake Error at builders/vpx.cmake:87 Cmake Error at builders/vpx.cmake:77 file not found WORK/desktop/cmake/windowsenv_libpath...

    Python库 | aws_lambda_builders-0.7.0-py3-none-any.whl

    "py3-none-any" 部分表示该轮子文件(wheel file)适用于Python 3解释器,不依赖特定操作系统或架构,这意味着它可以在任何支持Python 3的平台上使用。 在使用`aws_lambda_builders`时,开发者可以利用其内置的构建...

    nano_builders

    nano_builders

    opensource.builders:寻找开源替代品

    使用Gatsby CLI创建一个新站点,并指定博客启动器。 # clone this repo git clone https://github.com/junaid33/opensource.builders 开始开发。 导航到新站点的目录并启动。 cd opensource.builders yarn install...

    ob-web-server:Ocean Builders服务器的设计旨在通过提供帮助用户的工具来使他们对Ocean builders seapods进行控制

    海洋建筑商服务器Ocean Builders应用程序为seapod所有者提供了在任何iOS和Android设备上的完全控制,监视和自定义选项。 该系统旨在通过提供工具来帮助控制海洋吊舱创建过程,从而使用户能够控制海洋建造者的海洋...

    Python库 | cortex_python_builders-1.2.0-py3-none-any.whl

    这个库名为"Cortex Builders",版本为1.2.0,专为Python 3设计,支持所有平台(`none`表示它不特定于任何特定操作系统,`any`则表示它可以用于任何架构)。`.whl`文件是Python的二进制分发格式,它是Python的wheel...

    【设计模式】- 生成器模式(Builder)(csdn)————程序.pdf

    生成器模式,也称为建造者模式,是一种设计模式,用于创建复杂对象,它允许你按照一系列步骤来构造对象,而这些步骤可以通过不同的实现来产生不同形式的对象。生成器模式的核心在于分离了对象的构造过程和表示细节,...

    cloud-builders:Google Cloud Build常用的Builder映像和示例

    预构建的映像可在gcr.io/cloud-builders/... ,包括: bazel :运行工具 curl :运行工具 docker :运行工具 dotnet :运行工具 gcloud :运行工具 gcs-fetcher :从Google Cloud Storage有效地获取对象 git :...

    ng-builders:自定义Angular CLI构建器

    `ng-builders`库中的构建器可能包括但不限于以下几种: 1. **Firebase构建器**: 这些构建器专门用于与Firebase集成,可以方便地将Angular应用部署到Firebase Hosting,或者进行Firebase功能的其他配置。 2. **...

Global site tag (gtag.js) - Google Analytics