Effective Java 读书笔记
Item 1:考虑用静态工厂方法代替构造器
- 顾名思义就是使用静态方法来构造对象
优点 1:静态工厂方法与其它构造器不同的优点在于他们有名称
- 这样使用的好处是调用者能够通过名字来判别应该调用哪个构造器,比较通俗的例子如下:
public class Person {
private String gender;
private Person(String gender) {
this.gender = gender;
}
private static Person FEMALE = new Person("female");
private static Person MALE = new Person("male");
public static Person getAFemale() {
return FEMALE;
}
public static Person getAMale() {
return MALE;
}
.....
}
public class Main {
public static void main(String[] args) {
Person male = Person.getAMale();
Person female = Person.getAFemale();
......
}
}
优点2:静态工厂方法使得在获取一个类的实例化的时候,不必重新创建一个新的对象,降低了消耗,提升了性能
- 在高并发的情况下,如果一个对象不可变,那就应该考虑使用静态工厂方法来代替构造器,这样,就不用每次请求都创建新的对象。最好的例子就是
Boolean.ValueOf()
{
...
private static Boolean Boolean.TRUE = new Boolean(true);
private static Boolean Boolean.FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FAlSE;
}
...
}
优点3:应为构造器本身只能返回类对象本身的限制,静态工厂方法能够返回子类对象,最好的应用就是Service provider framework。Service provider framework能够成立的基础点就是静态工厂模式
- 稍后附上链接
优点4:结合泛型,当类的构造器的参数类型很长的时候,静态工厂方法能够简化代码,如下所示:
- 最常见的举例如下:
public class Main() {
public static void main(String[] args) {
//传统构造方法
HashMap<String, List<String>> mapWithTraditionalConstruct = new HashMap<String, List<String>>();
//静态工厂构造方法
HashMap<String, List<String>> mapWithNewConstruct = Maps.newHashMap();
}
}
//内部实现如下
public final class Maps {
private Maps() {}
...
public static <K, V> HashMap<K, V> newHashMap() {
return new HashMap<K, V>();
}
...
}
Item 2:当构造器需要多个参数的时候,考虑用Builder模式创建对象
- 假设有这样一种场景,使用effectiveJava中的例子,当类拥有多个属性,并且对象需要的属性根据不同的场景会不同,通常方法是使用重叠构造器模式
public Class Demo1 {
private String param1;
private String param2;
private String param3;
public Demo1(String param1) {
this.param1 = param1;
}
public Demo2(Strig param1, String param2) {
this.param1 = param1;
this.param2 = param2;
}
public Demo3(String param2, String param3) {
this.param2 = param2;
this.param3 = param3;
}
public Demo4(String param1, String param3) {
this.param1 = param1;
this.param3 = param3;
}
public Demo5(String param1, String param2, String param3) {
this.param1 = param1;
this.param2 = param2;
this.param3 = param3;
}
}
- 重叠式构造确实能够解决一部分问题,但是它大大的增加了代码的可读性以及coding,例如,当参数增加到了5的时候,构造函数的个数也随之增加到了C-5-5(5的组合)个。JavaBean模式能够很好的解决这一个问题:
private String param1;
private String param2;
private String param3;
public Demo1() {
}
public void setParam1(String param1) {
this.param1 = param1;
}
public void setParam2(String param2) {
this.param2 = param2;
}
public void setParam1(String param3) {
this.param3 = param3;
}
- 但是JavaBean有一个致命的缺陷:JavaBean的set方法阻止了类的不可变,这使得在多线程情况下需要耗费额外的精力来保证线程安全。builder模式孕育而生,它解决了重叠式构造器和javabean面临的两个问题,builder模式如下:
public class City() {
private int populationSize;
private double sexRatio;
private BigDecimal gdp;
private City(Builder builder) {
this.populationSize = builder.populationSize;
this.sexRatio = builder.sexRatio;
this.gdp = builder.gdp;
}
public static class Builder {
private int populationSize;
private double sexRatio;
private BigDecimal gdp;
public Builder() {
}
public Builder setPopulationSize(int populationSize) {
this.populationSize = populationSize;
return this;
}
public Builder setSexRatio(double sexRatio) {
this.sexRatio = sexRatio;
return this;
}
public Builder setGDP(BigDecimal gdp) {
this.gdp = gdp;
return this;
}
public City build() {
return new City(this);
}
}
}