ej3-1优先使用静态工厂方法而非构造函数来创建对象
背景
很早之前就已经自己翻译了,先简单的贴出来,并做一下回顾。
条款1 优先使用静态工厂方法而非构造函数来创建对象
允许客户端创建一个实例的传统方法是:提供一个公共构造函数;有另外一个必须成为每个程序员的编程技巧:优先使用类提供的只简单返回实例的公共静态工厂方法来创建对象。这有一个简单的Boolean类的例子:这个方法转换一个原生的boolean类型的值为一个Boolean的实例。
public static Boolean valueOf(boolean b){
return b?Boolean.TRUE:Boolean.FALSE;
}
注意这一点:类的静态工厂方法不同于设计模式的工厂设计模式。本条规约跟设计模式没有关联。
一个类可以通过静态工厂方法也可以使用公共构造函数提供给自己的客户端调用来创建实例,使用静态工厂方法而不是公共构造函数有优点也有缺点。
** 优点1:它有名字,可读性更好;**
构造函数的参数跟自己无关,没有描述返回对象;而良好命名的静态工厂方法客户端代码可读性更好,所以更容易使用;
//使用构造方法,返回一个BigInteger随机素数;
BigInteger(int , int , Random)
//更好的表达方式
public static BigInteger probablePrime();
一个类构造函数的签名格式是唯一的,程序员围绕这个限制提供了两个构造函数,他们区分的标准是不一样参数的类型组成的参数列表,这真的是一个糟糕的设计,使用这种API的人从来就没办法记住哪个构造函数对应哪个功能,并且容易误用导致调用错误;使用这些构造函数的人只能阅读代码,类文档没法区分。
因为静态工厂方法有名字,所以不存在区分的限制,在一个类有多个签名的构造函数的场景中,应该使用静态工厂方法替代构造函数,并且小心选择名字来区别;
优点2:不需要每次被调用的时候都创建一个新的对象;
这允许构造完毕的不可变类使用提前构建或者缓存的实例,避免创建不必要的重复的对象(分配重复的实例); Boolean.valueOf(boolean) 方法展示了这个技巧,它从来不创建对象,这个技巧类似于享元模式;如果创建代价昂贵的对象被频繁获取,它可以显著的提高性能;这个能力可以让类在任何时刻严格控制实例,这样的类叫做实例可控类,有几个理由应该编写实例可控类:
- 实例可控使类需要保证它是单例的实例数量可控;
- 需要保证没有两个相同的实例存在;如果a.equls(b) ; 有且只有a == b. 这是基本的享元模式。枚举类型提供了这个保证;
优点3:可以返回子类型,面向抽象编程或者说是接口编程,更灵活;
一个灵活的应用API可以返回非公开的对象,隐藏实现类从而形成契约API,这个技巧使得它可以成为基于接口的框架,接口提供自然的返回类型,(在java8之前,接口没有静态的方法,按照惯例,接口Type静态工厂方法被放到了一个不可实例化的指南类Types中;)
举个例子:java的Collections接口框架有45个种不同的应用实现,提供不可修改集合,同步集合等,几乎所有的这些实现通过一个不可实例化的类Collections的静态工厂方法来对外暴露;所有的返回对象都是非公开的的(即实际返回的是接口实现类或者返回类的子类)。这个集合框架的API比定义45个分开独立的公共类规模要小很多(它减少了集合类的数量负担,也减少了程序员必须掌握使用的API的类数量),程序员知道返回的对象精确的指出了它的接口,所以没有必要去阅读更多的实现类的文档。更进一步,使用这样一个静态工厂方法的客户端只需要参照接口而不用考虑实现类去使用,这是一个最佳实践。
在java8中,接口已经可以添加静态方法了,所以接口可以提供一个不可实例的有常规名字的指南类;接口的很多的公共静态成员放应该替代成接口本身。然而,仍然有必要把这样一个静态工厂方法实现代码放到分开的private 包下的类中;这是因为java8要求接口的静态成员必须是public,java9允许私有的静态方法,但是静态成员和静态内部类任然需要是public的;
原创不易,转载请注明出处。
ej3-1优先使用静态工厂方法而非构造函数来创建对象的更多相关文章
- <创建和销毁对象>经验法则——考虑用静态工厂方法代替公有构造方法
一.引出静态工厂方法 对于java类而言,为了让使用者获取它自身的一个实例化对象,会有以下方法: 1.该类提供一个公有的构造方法.在这种情况下,程序可以通过多个“new 构造方法”语句来创建类的任意多 ...
- Effective Java 读书笔记(一):使用静态工厂方法代替构造器
这是Effective Java第2章提出的第一条建议: 考虑用静态工厂方法代替构造器 此处的静态工厂方法并不是设计模式,主要指static修饰的静态方法,关于static的说明可以参考之前的博文&l ...
- 创建对象_工厂方法(Factory Method)模式 与 静态工厂方法
工厂方法模式: 定义:为创建对象定义一个接口,让子类决定实例化哪个类.工厂方法让一个类的实例化延迟至子类. 应用场景: 客户类不关心使用哪个具体类,只关心该接口所提供的功能: 创建过程比较 ...
- Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Java 的静态工厂方法
本文转载自:https://www.jianshu.com/p/ceb5ec8f1174 序:什么是静态工厂方法 Effective Java 2.1 静态工厂方法与构造器不同的第一优势在于,它们有名 ...
- 静态工厂方法VS构造器
我之前已经介绍过关于构建者模式(Builder Pattern)的一些内容,它是一种很有用的模式用于实例化包含几个属性(可选的)的类,带来的好处是更容易读.写及维护客户端代码.今天,我将继续介绍对象创 ...
- 比较 Java 静态工厂方法与构造函数
1 什么是静态工厂方法 Java 静态工厂方法是在方法前加上 public static,让这个方法变为公开.静态的方法.该方法返回该类的一个实例,就好像一个工厂生产出一个产品.所以称之为静态工厂方法 ...
- [原创]java WEB学习笔记102:Spring学习---Spring Bean配置:bean配置方式(工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean) 全类名
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- HttpSolrServer-采用静态工厂方法,创建HttpSolrServer单实例
HttpSolrServer线程安全,如果使用下面构造器,必须对所有的请求重用相同的实例.如果实例在运行中创建的,它可能会导致连接泄漏.推荐的做法就是保持每个solr服务url的HttpSolrSer ...
随机推荐
- P1045麦森数
P1045麦森数 #include<iostream> #include <cmath> #include <cstring> const int maxn = 1 ...
- eclipse 快速隐藏所有方法的代码块
java开发中往往一个class文件中会有很多方法,一个方法的实现代码有时候特别长 我个人就喜欢把无关的方法代码全部隐藏起来,只打开当前需要编辑的代码就行了(不喜欢看导航视图,容易头晕) Ctrl+s ...
- 1.WEB安全概述
一.WEB常见的安全性问题简介 XSS(Cross-Site Scripting):跨站脚本攻击漏洞 CSRF(Cross-site request forgery):跨站请求伪造 文件上传漏洞 SQ ...
- C++中的随机数
事情的开始是这样的,在大二的时候,写了几种排序算法,为了测试,就要为数组(或者容器)赋予一些随机初值,自然就用到了C/C++中的随机函数. 当时为了调用简单,将随机数赋值的过程写到了一个单独的函数里, ...
- Vue - 监听页面刷新和关闭
一,在 created中 注册 页面刷新和关闭事件 created() { window.addEventListener('beforeunload', e => this.test(e)) ...
- Python爬虫教程-爬取5K分辨率超清唯美壁纸源码
简介 壁纸的选择其实很大程度上能看出电脑主人的内心世界,有的人喜欢风景,有的人喜欢星空,有的人喜欢美女,有的人喜欢动物.然而,终究有一天你已经产生审美疲劳了,但你下定决定要换壁纸的时候,又发现网上的壁 ...
- MyBatis的2个核心对象:SqlSessionFactory、SqlSession
SqlSessionFactory SqlSessionFactory是单个数据库映射关系经过编译后的内存镜像,主要作用是创建SqlSession. InputStream inputStream = ...
- Batch批量替换hosts
hosts文件替换 工作需要,要修改很多计算机的hosts文件,采用bat批量完成 解决的问题: 1.pc工作在非管理员权限,右键管理员权限太麻烦,因此采用执行中申请管理员权限的方式 2.hosts和 ...
- URL构成及各个协议默认端口
url的构成:一般来说,http请求都会和URL地址有关,对于url来说一般由下面5个部分构成 .协议:通常就是第一个冒号之前的内容常见协议:http,https(http+ssl),ftp,ssh, ...
- ADV-299 宰羊 (java,过了30%)
问题描述 炫炫回了内蒙,肯定要吃羊肉啦,所有他家要宰羊吃. 炫炫家有N只羊,羊圈排成一排,标号1~N.炫炫每天吃掉一只羊(这食量!其实是放生啦),吃掉的羊的邻居会以为它被放生了,然后又会告诉他们的邻居 ...