构造函数必须没有代码

构造函数中应完成多少工作? 在构造函数内部进行一些计算然后封装结果似乎是合理的。 这样,当对象方法需要结果时,我们将准备好它们。 听起来是个好方法? 不,这不对。 这是一个坏主意,原因有一个:它阻止了对象的组合并使它们不可扩展。

杀死比尔2(2004)由昆汀·塔伦蒂诺(Quentin Tarantino)

杀死比尔 2(2004)由昆汀·塔伦蒂诺(Quentin Tarantino)

假设我们正在制作一个代表一个人的名字的接口:

interface Name {String first();
}

很简单,对不对? 现在,让我们尝试实现它:

public final class EnglishName implements Name {private final String name;public EnglishName(final CharSequence text) {this.parts = text.toString().split(" ", 2)[0];}@Overridepublic String first() {return this.name;}
}

这怎么了 更快吧? 它仅将名称分成几部分,然后将其封装。 然后,无论我们调用first()方法有多少次,它都将返回相同的值,并且无需再次进行拆分。 但是,这是有缺陷的想法! 让我向您展示正确的方法并说明:

public final class EnglishName implements Name {private final CharSequence text;public EnglishName(final CharSequence txt) {this.text = txt;}@Overridepublic String first() {return this.text.toString().split("", 2)[0];}
}

这是正确的设计。 我可以看到你在微笑,所以让我证明我的观点。

不过,在开始验证之前,让我请您阅读本文: 可组合装饰器与命令式实用方法 。 它解释了静态方法和可组合装饰器之间的区别。 上面的第一个代码段看起来非常像一个对象,它非常接近命令式实用程序方法。 第二个例子是一个真实的对象。

在第一个示例中,我们正在滥用new运算符,并将其转换为静态方法,该方法会在此时此刻为我们进行所有计算。 这就是命令式编程的目的。 在命令式编程中,我们立即执行所有计算并返回完全准备好的结果。 相反,在声明式编程中,我们尝试尽可能长时间地延迟计算。

让我们尝试使用我们的EnglishName类:

final Name name = new EnglishName(new NameInPostgreSQL(/*...*/)
);
if (/* something goes wrong */) {throw new IllegalStateException(String.format("Hi, %s, we can't proceed with your application",name.first()));
}

在此代码段的第一行中,我们只是创建一个对象的实例并将其标记为name 。 我们还不想进入数据库并从那里获取全名,将其拆分为多个部分,然后将其封装在name 。 我们只想创建一个对象的实例。 这种解析行为对我们来说将是一个副作用,在这种情况下,将减慢应用程序的速度。 如您所见,如果出现问题,我们可能只需要name.first() ,而我们需要构造一个异常对象。

我的观点是,在构造函数内部进行任何计算都是一种不好的做法,必须避免这样做,因为它们是副作用,对象所有者不要求这样做。

您可能会问,重用name期间的性能如何? 如果我们创建了EnglishName的实例,然后调用了name.first()五次,则最终将对String.split()方法进行五次调用。

为了解决这个问题,我们创建了另一个类,一个可组合的decorator ,它将帮助我们解决这个“重用”问题:

public final class CachedName implements Name {private final Name origin;public CachedName(final Name name) {this.origin = name;}@Override@Cacheable(forever = true)public String first() {return this.origin.first();}
}

我正在使用jcabi-aspects的Cacheable批注,但是您可以使用Java(或其他语言)可用的任何其他缓存工具,例如Guava Cache :

public final class CachedName implements Name {private final Cache<Long, String> cache =CacheBuilder.newBuilder().build();private final Name origin;public CachedName(final Name name) {this.origin = name;}@Overridepublic String first() {return this.cache.get(1L,new Callable<String>() {@Overridepublic String call() {return CachedName.this.origin.first();}});}
}

但是请不要使CachedName可变并且延迟加载-这是一种反模式,我之前在“ 对象应该是不可变的”中已经讨论过。

这是我们的代码现在的外观:

final Name name = new CachedName(new EnglishName(new NameInPostgreSQL(/*...*/))
);

这是一个非常原始的示例,但我希望您能理解。

在此设计中,我们基本上将对象分为两部分。 第一个知道如何从英文名称中获取名字。 第二个知道如何将计算结果缓存到内存中。 现在,作为这些类的用户,我将决定如何正确使用它们。 我将决定是否需要缓存。 这就是对象构成的全部内容。

让我重申一下,构造函数中唯一允许的语句是赋值。 如果您需要在此处放置其他内容,请开始考虑进行重构-您的课程肯定需要重新设计。

翻译自: https://www.javacodegeeks.com/2015/05/constructors-must-be-code-free.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360300.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一个路由器两个网段互通_如何判断两个IP地址是否在同一个网段?什么是子网掩码?...

前几天咱们了解&#xff1a;三种方法告诉你项目超过255个摄像机怎么设置IP?什么是公网ip&#xff1f;什么又是内网ip&#xff1f;为什么ip地址通常以192.168开头&#xff1f;也学习了&#xff1a;二、三层交换机与路由器的区别&#xff01;但是有好多人对IP这个概念还是不太清…

http 路径 |_HTTP 请求與响应的格式及 curl 命令使用

介绍 HTTP&#xff0c;主要内容有HTTP 请求包括哪些部分&#xff0c;如何用Chrome开发者工具查看 HTTP 请求内容HTTP 响应包括哪些部分&#xff0c;如何用Chrome开发者工具查看 HTTP 响应内容如何使用 curl 命令HTTP 请求的格式1 动词 路径 协议/版本 2 Key1: value1 2 Key2: v…

华为y7可以人脸识别吗_华为手机经常弹出“系统更新”提示,可以不更新吗?看完涨知识了...

众所周知&#xff0c;无论是手机&#xff0c;还是电脑&#xff0c;我们所使用的系统到了一定的时间&#xff0c;都会进行“系统更新”&#xff0c;尤其是我们使用的苹果手机、华为手机等&#xff0c;就经常会跳出提示&#xff0c;提醒用户“更新系统”&#xff0c;尤其是当我们…

Apache骆驼丝攻示例

如果您想监视&#xff0c;调试&#xff0c;排除流经路由的消息&#xff0c;而又不必从通道中永久消耗消息&#xff0c;那么就需要使用电线 。 有线分流器充当接收者列表&#xff0c;该列表消耗输入通道之外的消息并将其发布到两个输出通道。 第一个是作为主要信道的实际目的地…

参考文献中会议名称怎么缩写_期刊缩写查询总结

介绍英文论文写作中&#xff0c;经常会插入参考文献。那么参考文献中的期刊名称&#xff0c;时常需要使用缩写。但是有时候&#xff0c;查了半天&#xff0c;怎么也查不着&#xff0c;让人抓狂。今天小编总结了几个查询期刊缩写的网址&#xff0c;方便大家进行期刊缩写的查询。…

7. SVM松弛变量

我们之前讨论的情况都是建立在样例线性可分的假设上&#xff0c;当样例线性不可分时&#xff0c;我们可以尝试使用核函数来将特征映射到高维&#xff0c;这样很可能就可分了。然而&#xff0c;映射后我们也不能100%保证可分。那怎么办呢&#xff0c;我们需要将模型进行调整&…

mysql 8.0认证失败_解决mysql8.0因密码认证插件导致的链接不上

简介今天在迁移zabbix的数据库&#xff0c;每次链接到自己的mysql都报错&#xff0c;mysqlAuthentication plugin caching_sha2_password cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_passwordzabbix总是提示**** MySQL server is not available. Waiting 5 secon…

ActionScript 3.0入门:Hello World、文件读写、数据存储(SharedObject)、与JS互调

近期项目中可能要用到Flash存取数据&#xff0c;并与JS互调&#xff0c;所以就看了一下ActionScript 3.0&#xff0c;现把学习结果分享一下&#xff0c;希望对新手有帮助。 目录 ActionScript 3.0简介 Hello World 文件读写 数据存储(SharedObject) 与JS互调 ActionScript 3.0简…

Quasar和Akka –比较

actor模型是用于容错和高度可扩展系统的设计模式。 角色是独立的工作程序模块&#xff0c;仅通过消息传递与其他角色进行通信&#xff0c;可以与其他角色隔离而失败&#xff0c;但是可以监视其他角色的故障并在发生这种情况时采取一些恢复措施。 参与者是简单&#xff0c;孤立但…

dlgdata.cpp错误提示 解决方案

1、在测试编写继承CStatic类组件时候&#xff0c;发现在调用调试过程中弹出一个错误&#xff0c;点忽略还可以继续运行。如下图&#xff1a; 2、dlgdata.cpp此文件是VS安装目录\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\mfc中的文件&#xff0c;而出现此错误一般是所…

mysql主从复制时间配置_MySQL主从复制配置

环境CentOS 7.5Docker 1.13.1MySQL 8.0.16基于以上环境启动三个mysql容器&#xff0c;一个为master&#xff0c;二个为slavemaster和slave使用的mysql版本是完全一致的&#xff0c;未测试不同版本的mysql配置master编辑配置文件编辑master的配置文件my.cnf$ vim /usr/mysql/con…

C语言操作符优先级

转自&#xff1a;http://www.cnblogs.com/xiehy/archive/2010/02/04/1663825.html 优先级 运算符 含 义 要求运算 对象的个数 结合方向 1 () [] -> . 圆括号 下标运算符 指向结构体成员运算符 结构体成员运算符 自左至右 2 ! 逻辑非运算符 1 (单目运算符)…

Win7下硬盘安装Redhat双系统

Win7下硬盘安装Redhat Linux 形成双系统过程详解 需要软件 EasyBCD2.0 和 linux ISO 系统镜像 RedHat linux下载地址&#xff1a;http://www.linuxidc.com/Linux/2013-01/78017.htm 安装前准备工作: 1 一个 Windows 盘 D E F 任选其一都可以&#xff0c;将其格式化为FAT32 格式…

java rmi漏洞工具_学生会私房菜【20200924】Weblogic WLS核心组件反序列化命令执行突破(CVE20182628)漏洞复现...

学生会私房菜学生会私房菜是通过学生会信箱收集同学们的来稿&#xff0c;挑选其中的优质文档&#xff0c;不定期进行文档推送的主题。本期文档内容为&#xff1a;Weblogic WLS核心组件反序列化命令执行突破(CVE-2018-2628)漏洞复现》作者介绍&#xff1a;ChowChow&#xff0c;一…

ASP.NET伪静态-无法读取配置文件,因为它超过了最大文件大小的解决办法

一直都在使用微软URLRewriter&#xff0c;具体的使用方法我就不多说了&#xff0c;网上文章很多。 但最近遇到一个问题&#xff0c;就是当web.config文件里面设置伪静态规则过多&#xff0c;大于2M的时候&#xff0c;就报错&#xff1a;无法读取配置文件&#xff0c;因为它超过…

java定义list_我的Java Web之路59 - Java中的泛型

本系列文章旨在记录和总结自己在Java Web开发之路上的知识点、经验、问题和思考&#xff0c;希望能帮助更多(Java)码农和想成为(Java)码农的人。目录介绍再谈Java中的类型为什么需要泛型&#xff1f;Java中的泛型泛型类型泛型方法总结介绍还记得我在这篇文章(我的Java Web之路3…

通过更改透明度使图片为透明

使用AlphaBlend函数 函数功能 该函数用来显示具有指定透明度的图像。函数原型 AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int hHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,BLENDFUNCTION blendFunc…

(转)CocoaPods:管理Objective-c 程序中各种第三方开源库关联

在我们的iOS程序中&#xff0c;经常会用到多个第三方的开源库&#xff0c;通常做法是去下载最新版本的开源库&#xff0c;然后拖拽到工程中。 但是&#xff0c;第三方开源库的数量一旦比较多&#xff0c;版本的管理就非常的麻烦。有没有什么办法可以简化对第三方库的管理呢&…

为什么子进程每次执行顺序不一样_看完这篇还不懂Redis的RDB持久化,你来打我...

推荐观看&#xff1a;Redis缓存穿透的终极解决方案&#xff0c;手写布隆过滤器_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.comP8架构师串讲&#xff1a;Redis&#xff0c;zookeeper&#xff0c;kafka&#xff0c;Nginx等技术_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​w…

Spring XD用于数据提取

Spring XD是一个功能强大的工具&#xff0c;它是一组可安装的Spring Boot服务&#xff0c;可以独立运行&#xff0c;在YARN或EC2之上运行。 Spring XD还包括一个管理UI网站和一个用于作业和流管理的命令行工具。 Spring XD是一组功能强大的服务&#xff0c;可与各种数据源一起使…