使用构建器(Builder模式)创建多属性的对象

​ 用静态工厂或者构造器来创建对象,但是静态工厂和构造器都有局限性——即无法扩展到多参数的对象。

​ 我们可以想到用重叠构造器和JavaBean来进行创建多参数对象,重叠构造器在应用到多参数的时候,客户端会很难维护,JavaBean模式在set的过程中可能存在状态不一致的问题。JavaBean模式使得把类做成不可变的可能性不复存在。

​ 这时我们可以考虑使用Builder模式

package com.fanggeek;

public class NutritionFacts {
    private final int servingSize;
    private final int calories;
    private final int servings;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;

    public static class Builder{
        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;
        }
    }
    private NutritionFacts(Builder builder){
        servingSize = builder.servingSize;
        servings =builder.servings;
        calories = builder.calories;
        fat = builder.fat;
        sodium = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }
}

Builder 模式模拟了具有具名的可选的参数。

Builder模式也适用于类层次结构。

package com.fanggeek;

import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;

/**
 * Builder模式构建器
 * We should know our goal is to make a Object pizza with different property;
 * So I decide to make a EnumSet as a collection to collect properties;
 * Then a Abstract Biulder is needed for us to make the clone Enumset;
 */
public abstract class Pizza {

    /**
     * the properties in the object
     */
    public enum Topping{HAM ,MUSHROOM,ONION,PEPPER,SAUSACE}

    /**
     * EnumSet to collect the properties in the object
     */
    final Set<Topping> toppings;


    /**
     * @param <T>
     */
    abstract static class Builder<T extends Builder<T>>{
        EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);

        public T addTopping(Topping topping){
            toppings.add(Objects.requireNonNull(topping));
            return self();
        }
        abstract Pizza build();
        //SubClass must override this method return this
        protected abstract T self();
    }
    Pizza(Builder<?> builder){
        toppings = builder.toppings.clone();
    }
}
posted @ 2021-05-15 12:15  Cwoke  阅读(240)  评论(0)    收藏  举报