第一条:考虑用静态工厂方法代替构造器

  静态工厂方法:只是一个返回类实例的静态方法。

例:

  public static Boolean valueOf(boolean b){

    return b ? Boolean.TRUE : Boolean.FALSE;

  }

  提供静态工厂方法而不是公有的构造器的优势:

  1.静态工厂方法与构造器不同的第一大优势在于,它们有名称。(避免了多个构造器带来的参数过多,不方便记忆和使用)

  2.静态工厂方法与构造器不同的第二大优势在于,不必在每次调用它们的时候都创建一个新对象。(例如:单例)

  例:Boolean.valueOf(boolean);

  实例受控的类:原因:确保唯一或不可实例化。

  3.静态工厂方法与构造器不同的第三大优势在于,它们可以返回原返回类型的任何子类类型的对象。

  4.静态工厂方法与构造器不同的第四大优势在于,在创建参数化类型实例的时候,它们使代码变得更加简洁。

  复杂的:Map<String, List<String>> m = new HashMap<String, List<String>>();

  假设HashMap提供了如下的静态工厂:

  public static <K, V> HashMap<K, V> newInstance(){

    return new HashMap<K, V>();

  }

  Map<String, List<String>> m = HashMap.newInstance();

  5.静态工厂方法的主要缺点在于,类如果不含公有的或者受保护的构造器,就不能被子类化

  6.静态工厂方法的第二个缺点在于,它们与其他的静态方法实际上没有任何区别。

  valueOf、of、getInstance、newInstance、getType、newType

第二条:遇到多个构造器参数时要考虑用构造器

  静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。

  面对必须的参数和可选的参数的构造器:

  1.习惯采用重叠构造器

  写多个构造器,第一个是必须参数的构造器,第二个是必须参数加上一个可选参数组成的构造器,第三个是必须参数加上两个个可选参数组成的构造器....

  重叠构造器模式可行,但是当有许多参数的时候,客户端代码会比较难写,并且难以阅读。

  2.采用javaBeans模式

  创建一个无参的构造器,然后利用setter方法来设置必须的参数以及每个相关的可选参数。  

  javaBeans模式自身的缺点:

    1.构造过程被分到几个调用中,在构造过程中JavaBean可能处于不一致的状态。类无法仅仅通过检验构造器参数的有效性来保证一致性。

    2.JavaBeans模式阻止了类做成不可变的可能。这可能需要程序员付出额外的努力来确保它的线程安全。

  3.采用Builder模式

  既能保证像重叠构造器模式那样的安全性,也能保证像JavaBeans模式那么好的可读性。 不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或静态工厂),得到一个builder对象。然后客户端在builser对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用午餐的builder方法来生成不可变的对象。

示例:

package unit.test.no2;

public class NutritionFacts {
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;
    
    public static class Builder{
        //Required parameters
        private final int servingSize;
        private final int servings;
        
        //Optional parameters - initialized to default values
        private int calories     = 0;
        private int fat          = 0;
        private int sodium       = 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 sodium(int val) {
            sodium =val;
            return this;
        }
        public Builder carbohydrate(int val) {
            carbohydrate =val;
            return this;
        }
        
        public NutritionFacts build() {
            return new NutritionFacts(this);
        }
        
    }
    
    
    public NutritionFacts(Builder builder) {
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
        sodium = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }
    
}
View Code

相关文章: