[Read Effective Java] Kapitel 2 Punkt 2 "Betrachten Sie einen Builder, wenn Sie mit einer großen Anzahl von Konstruktorparametern konfrontiert werden."

Betrachten Sie den Builder, wenn Sie mit zahlreichen Konstruktorparametern konfrontiert werden

Wenn Sie eine Klasse erstellen, bei der Sie beim Neueintritt viele Parameter übergeben müssen Die Verwendung von "Builder" ist sowohl für die Lesbarkeit als auch für die Sicherheit gut

Beispielcode

Nutrition Facts ist eine Klasse, die Nährstoffkomponenten darstellt Betrachten Sie drei Muster, wobei Sie als Beispiel die Menge für eine Person, die Menge pro Behälter, die Kalorien für eine Person usw. nehmen. ・ Teleskopkonstruktormuster Der Nachteil ist, dass es bei vielen Parametern schwierig ist zu verstehen, was beim Neueintritt als Argument zu übergeben ist, und die Lesbarkeit nimmt ebenfalls ab.

・ JavaBeans-Muster Im Gegensatz zum Terescoping-Konstruktormuster ist es besser lesbar, erzeugt jedoch beim Festlegen von Parametern einen inkonsistenten Status.

・ Builder-Muster Das Beste aus Terescorping-Konstruktoren und JavaBeans!

Beispiel 1


//Tereskopierendes Konstruktormuster
public class NutritionFacts{
    private final int servingSize;  //(mL)Verpflichtend
    private final int servings;     //(Pro Container)Verpflichtend
    private final int calories;     //Möglichkeit
    private final int fat;          //(g)Möglichkeit
    private final int sodium;       //(mg)Möglichkeit
    private final int carbohydrate; //(g)Möglichkeit

    public NutritionFacts(int servingSize, int servings){
        this(servingSize, servings, 0, 0, 0, 0);
    }

    public NutritionFacts(int servingSize, int servings, 
             int calories ){
        this(servingSize, servings, calories, 0, 0, 0);
    }
    
    public NutritionFacts(int servingSize, int servings,
            int calories, int fat ){
        this(servingSize, servings, calories, fat, 0, 0);
    }

    public NutritionFacts(int servingSize, int servings,
            int calories, int fat, int sodium ){
        this(servingSize, servings, calories, fat, sodium, 0);
    }

    public NutritionFacts(int servingSize, int servings,
            int calories, int fat, int sodium, carbohydrate ){
        this.servingSize   = servingSize;
        this.servings      = servings;
        this.calories      = calories;
        this.fat           = fat;
        this.sodium        = sodium;
        this.carbohydrate  = carbohydrate;
    }
}

//Es ist schwer zu sehen, wann es neu ist
NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);

Beispiel 2


//JavaBeans-Muster
public class NutritionFacts{
    private int servingSize  = -1; //(mL)Verpflichtend
    private int servings     = -1; //(Pro Container)Verpflichtend
    private int calories     = 0;  //           
    private int fat          = 0;  //(g)        
    private int sodium       = 0;  //(mg)       
    private int carbohydrate = 0;  //(g)        

    public NutritionFacts(){ }

    //Setter
    public void setServingSize(int val)  { servingSize = val;}
    public void setServings(int val)     { servings = val;}
    public void setCalories(int val)     { calories = val;}
    public void setFat(int val)          { fat = val;}
    public void setSodium(int val)       { sodium = val;}
    public void setCarbohydrate(int val) { carbohydrate = val;}
}

//Es ist leicht zu erkennen, wenn es neu ist, aber es ist ein kleines Problem, wenn während der Einstellung darauf zugegriffen wird
NutritionFact cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);

Beispiel 3


//Builder-Muster
public class NutritionFacts{
    private final int servingSize;  //(mL)       
    private final int servings;     //(Pro Container)
    private final int calories;     //           
    private final int fat;          //(g)        
    private final int sodium;       //(mg)       
    private final int carbohydrate; //(g)        

    public static class Builder{
        //Erforderliche Parameter
        private final int servingSize;  //(mL)       
        private final int servings;     //(Pro Container)
        
        //Optionale Parameter
        private int calories     = 0;  //           
        private int fat          = 0;  //(g)        
        private int sodium       = 0;  //(mg)       
        private int carbohydrate = 0;  //(g)   

        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);
       }
    }

    private NutritionFacts(Builder builder){
         servingSize  = builder.servingSize;
         servings     = builder.servings;
         calories     = builder.calories;
         fat          = builder.fat;
         sodium       = builder.sodium;
         carbohydrate = builder.carbohydrate;
    }
}

//Im Neuzustand leicht zu sehen und sicher!
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
    calories(100).sodium(35).carbohydrate(27).build();

Recommended Posts

[Read Effective Java] Kapitel 2 Punkt 2 "Betrachten Sie einen Builder, wenn Sie mit einer großen Anzahl von Konstruktorparametern konfrontiert werden."
[Read Effective Java] Kapitel 2 Punkt 4 "Unmöglichkeit der Instanziierung mit privatem Konstruktor erzwingen"
[Read Effective Java] Kapitel 2 Punkt 1 "Betrachten Sie statische Factory-Methoden anstelle von Konstruktoren"
[Read Effective Java] Kapitel 3 Punkt 12 "Berücksichtigung der Implementierung von Comparable"
[Read Effective Java] Kapitel 2 Punkt 3 "Singleton-Eigenschaften mit privatem Konstruktor oder Aufzählungstyp erzwingen"
[Read Effective Java] Kapitel 3 Punkt 9 "Wenn Sie equals überschreiben, überschreiben Sie immer hashCode"
[Read Effective Java] Kapitel 2 Punkt 5 "Vermeiden Sie die Erstellung unnötiger Objekte"
[Read Effective Java] Kapitel 2 Punkt 7 "Vermeiden Sie Finalizer"
[Read Effective Java] Kapitel 3 Punkt 8 "Wenn Sie gleich überschreiben, befolgen Sie den allgemeinen Vertrag"
[Read Effective Java] Kapitel 3 Punkt 10 "Immer toString überschreiben"
[Read Effective Java] Kapitel 2 Punkt 6 "Veraltete Objektreferenzen entfernen"
[Java] Vereinigen Sie diese NG, wenn eine Methode mit einer großen Anzahl von Zeilen mithilfe von schwarzer Magie erkannt wird
Mit dem effektiven privaten Java-Konstruktor nicht unveränderlich erzwingen