内容简介:Effective Java 第二版笔记之考虑使用静态工厂方法代替构造器
创建对象最直接的想法就是通过 new 调用构造器,其实大多数情况下应当通过自己写一个静态公有方法,返回类的实例,比如下面这个方法:
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
和直接使用构造器相比,使用静态工厂方法具有以下优点:
- 静态工厂方法可以根据用途自己定义名称(不必与类相同),可读性更强
- 静态工厂方法可能不用在每次调用时都创建新对象
- 静态工厂方法可以返回声明类型的子类型的实例
下面分别阐述这三个优点。
静态工厂方法可以根据用途自己定义名称
构造器的方法名只能使用类名,如果有多个构造器,只能通过参数类型甚至顺序来区分,这样可读性非常差,而且不容易记,调用的时候很容易出错。
public class TantanitReader {
private int age;
private String loginName;
private String realName;
private String career;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public String getCareer() {
return career;
}
public void setCareer(String career) {
this.career = career;
}
}
比如在上面的例子中,类 TantanitReader 表示我的官方博客 tantanit.com 的读者信息,其中 age 表示年龄,loginName 表示登录名,realName 表示真实姓名,career 表示职业,除了 age 是 int 类型之外,其它几个都是字符串类型。
假设现在需要根据年龄和登录名,创建一个读者,使用构造器的话,代码如下:
public TantanitReader(int age, String loginName) {
this.age = age;
this.loginName = loginName;
}
假设又有一个场景,需要根据年龄(int 类型)和真实姓名(String 类型)创建读者,如果使用构造器的话,参数类型和上一个构造器相同,要解决这个问题呢?机智如你,一定想到通过对调参数顺序这个取巧(而不优雅)的方法,来规避这个问题。
public TantanitReader(String realName, int age) {
this.realName = realName;
this.age = age;
}
如果一个类要通过构造器创建读者,就需要根据这两个构造器的参数顺序记住各自的用法,是不是很容易记错啊。就算记住了也要查文档或者看看 TantanitReader 这个类的源文件,再确认一遍吧。
好了,又来了一个场景,需要根据年龄(int 类型)和职业创建读者,如果使用构造器的话,相信聪明如你,也是没有办法了。
所以,应当使用静态工厂方法来代替构造器。下面的代码很好地解决了这个问题:
public static TantanitReader getByAgeAndLoginName(int age,String loginName){
TantanitReader tantanitReader=new TantanitReader();
tantanitReader.setAge(age);
tantanitReader.setLoginName(loginName);
return tantanitReader;
}
public static TantanitReader getByAgeAndRealName(int age,String realName){
TantanitReader tantanitReader=new TantanitReader();
tantanitReader.setAge(age);
tantanitReader.setRealName(realName);
return tantanitReader;
}
public static TantanitReader getByAgeAndCareer(int age,String career){
TantanitReader tantanitReader=new TantanitReader();
tantanitReader.setAge(age);
tantanitReader.setCareer(career);
return tantanitReader;
}
三个方法使用不同的名称,并且在名称中暗示了参数的顺序,这样,在调用的时候,就不容易出错,也不用再查看文档或构造函数的源码了。
静态工厂方法可能不用在每次调用时都创建新对象
使用静态工厂方法,在有些使用场景下,可以重复使用一个提前生成的对象,或者从缓存中获取一个对象,而不用创建一个新的对象。文章开头的例子中的 Boolean.valueOf(boolean)方法,调用时就不用创建新的对象。这样节省了内存开销,也提高了性能。同时,和每次都 new 一个新的对象,都是不同的对象相比,在这种重复使用的场景中,每次返回的对象都是严格意义相同的对象,可以做到对象级别的控制。这种控制对单例和不可实例化的使用场景很有用,并且可以放心的使用 == 代替 equals 方法,以提高性能。比如枚举类就使用了这样的技术。
静态工厂方法可以返回声明类型的子类型的实例
构造函数,只能返回该类的实例,不能返回该类的子类的实例,静态工厂方法不受这个限制,因此可以很好地使用 Java 语言的多态性。在方法声明返回值类型为父类型,甚至接口类型,而返回子类型或接口的某个类型的具体实现。这样,将来想返回其它子类型或接口的其它实现时,只要直接修改方法体,不用改方法声明,不影响调用方的使用。
谈谈 IT的文章均为原创或翻译(翻译会注明外文来源),转载请以链接形式标明本文地址: http://tantanit.com/effectiv-java-static-method-replace-constructor/
欢迎关注官方微信公众号获取最新原创文章
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Java类 静态代码块、构造代码块、构造函数初始化顺序
- 解读Java静态代码块和构造代码块
- Effective Java 第二版笔记之考虑使用静态工厂方法代替构造器
- Effective Java in Kotlin第一条: 考虑用静态工厂方法而不是构造器
- TS 的构造签名和构造函数类型是啥?傻傻分不清楚
- 只有你能 new 出来!.NET 隐藏构造函数的 n 种方法(Builder Pattern / 构造器模式)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Inside Larry's and Sergey's Brain
Richard Brandt / Portfolio / 17 Sep 2009 / USD 24.95
You’ve used their products. You’ve heard about their skyrocketing wealth and “don’t be evil” business motto. But how much do you really know about Google’s founders, Larry Page and Sergey Brin? Inside......一起来看看 《Inside Larry's and Sergey's Brain》 这本书的介绍吧!