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 ...
随机推荐
- day4-2数组及方法
数组: Js数组 可以存放任意数据类型的数据 如果索引大于数组的长度,数组自动增加到该索引值加1的长度 var arr = ["terry","larry",& ...
- Python中self的用法
在Python类中规定,函数的第一个参数是实例对象本身,并且约定俗成,把其名字写为self.其作用相当于java中的this,表示当前类的对象,可以调用当前类中的属性和方法. 在python中,类是通 ...
- springmvc常用注解详解
1.@Controller 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ...
- 在ng-repeat 中使用 ng-click
angular 中使用 ng-repeat 过程中,有时需要绑定 事件 click ,使用ng-click ,但是并没有效果,此时应该使用 data-ng-click 替代 ng-click ,并且 ...
- 写给想要入门python或者正在入门python的小朋友们
写在前面: 最近好像python挺火,虽然我也在天天写python,但是python毕竟是动态语言,就拿常被人吐槽的java来说,python绝大不多数地方是不如java的.python只能是你的一个 ...
- js——form表单验证
用js实现一个简易的表单验证 效果: 代码: <html> <head> <title>js校验form表单</title> <meta char ...
- python中主要存在的四种命名方式:
1.object -- 公用方法 2._object -- 办保护 (1)被看做是‘protect’,意思是只用类对象和自来对象自己能访问的变量 (2)在模块或类外不可以使用,不能用 ‘from m ...
- JSP数据交互二
1.JSP内置对象:JSP内置对象是 Web 容器创建的一组对象,不用通过手动new就可以使用2.JSP9大内置对象: 对象名称 类型 request (请求对象) javax.servl ...
- 如何解决ajax跨域请求?
1.什么是跨域? a.域名不同 b.域名相同,端口不同 注:只有域名相同,端口相同时,才可以访问数据 可以使用jsonp解决ajax跨域请求的问题. 2.什么是jsonp? Jsonp其实就是一个跨域 ...
- vue 组件 - 函数统一调用(自定义钩子)
vue 组件继承方法 var childComponent = Vue.extend( { extends: baseComp, // 继承基础组件方法 template:template, wait ...