第一条 考虑用静态工厂方法代替构造器
构造函数:一般用来初始化成员属性和成员方法的,即new对象产生后,就调用了对象了属性和方法。
静态工厂方法:直接可以通过静态方法来实例化一个对象,例如:HelloWorldFactory.getInstance()
1.1 静态工厂方法与构造器不同的第一优势在于,它们有名字
java中的构造函数要求与类名相同,这就导致构造函数的名称不够灵活,不能准确描述返回值。
1.2 静态工厂方法不用每次调用时都创建新对象
1.3 静态工厂方法可以返回原返回类型的子类
class Person {
public static Person getInstance() {
return new Player();
}
}
class Player extends Person{}
class Cooker extends Person{}
1.4 静态工厂方法在创建带泛型的实例时,能使代码变得简洁
个人认为本条没用途,目前创建带泛型的实例可以通过
Map<String, List<String>> map = new HashMap<>();
来创建,同样代码简洁。
第二条 遇到多个构造器参数时要考虑构建器
静态工厂和构造器都不能很好地扩展到大量的可选参数。
/**
* @author 刘仁楠
* @date 2018/7/11 9:39
* 本类表示包装食品外的营养成分标签,这些标签中有些域是必须的,有些是可选的
*/
public class NutritionFacts {
/**
* 份量(required)
*/
private final int servingSize;
/**
* 一个人的量(required)
*/
private final int servings;
/**
* 热量(optional)
*/
private final int calories;
/**
* 脂肪(optional)
*/
private final int fat;
/**
* 钠(optional)
*/
private final int soidum;
/**
* 碳水化合物(optional)
*/
private final int carbohydrate;
public static class Builder {
/**
* 必选
*/
private final int servingSize;
private final int servings;
/**
* 可选
*/
private int calories = 0;
private int fat = 0;
private int soidum = 0;
private int carbohydrate = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder soidum(int val) {
soidum = val;
return this;
}
public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
soidum = builder.soidum;
carbohydrate = builder.carbohydrate;
}
@Override
public String toString() {
return "NutritionFacts{" +
"servingSize=" + servingSize +
", servings=" + servings +
", calories=" + calories +
", fat=" + fat +
", soidum=" + soidum +
", carbohydrate=" + carbohydrate +
'}';
}
public static void main(String[] args) {
NutritionFacts cocaCola = new Builder(240,8).calories(100).build();
System.out.println(cocaCola);
}
}
结果:
第三条 用私有构造器或枚举类型强化Singleton属性
singleton:仅被实例化一次的类
public enum Person {
instance("小强");
private final String name;
private Person(String name){
this.name = name;
}
public String getVal(){
return this.name;
}
}
public class Main {
public static void main(String[] args) {
Person person_a = Person.instance;
Person person_b = Person.instance;
System.out.println(person_b.getVal());
System.out.println(person_a == person_b);
}
}
第四条 通过私有构造器强化不可实例化的能力
某些只包含静态方法或静态域的类不需要被实例化,比如工具类,在这种情况下要确保其不会被实例化。
工具类之类的类不需要实例化,但也不必格外关注它的实例化问题。
第五条 避免创建不必要的对象
一般来说,最好能够重用对象,而不是在每次需要时创建一个相同功能的新对象。
public class Person {
private final Date birthday;
private static final Date BOOM_START;
private static final Date BOOM_END;
public Person(Date birthday) {
this.birthday = birthday;
}
static {
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
c.set(1946, Calendar.JANUARY, 1, 0, 0, 0);//将时间设置为1946年1月1日0时0分0秒
BOOM_START = c.getTime();
c.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = c.getTime();
}
public boolean isBabyBoomer() {
return birthday.compareTo(BOOM_START) >= 0 &&
birthday.compareTo(BOOM_END) < 0;
}
}
使用静态方法,是对象初始化时创建一次即可。