内容简介: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 / 构造器模式)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。