Jakdor
Jakdor

Reputation: 11

Long list of arguments

I'm having trouble figuring out how to organize the constructor.

Is the constructor supposed to take all the variables?

I create an instance of a PizzaOrder by invoking the constructor, and passing it the values in firstName, pizzaSizeInInches, pizzaType, cheeseTopping, pepperoniTopping, sausageTopping, onionTopping, mushroomTopping.

public static double calculatePizzaCost() {

    double cost = 12.99;            //cost of the pizza     

    String toppings = "";          //list of toppings     
    int numberOfToppings = 0;      //number of toppings
    String crust = "";
    final double TOPPING_PRICE = 1.25;

    if (aPizzaOrder.getHandThinDeep() == 'h' || aPizzaOrder.getHandThinDeep() == 'H') {
        crust = "Hand-Tossed";
    } else if (aPizzaOrder.getHandThinDeep() == 't' || aPizzaOrder.getHandThinDeep() == 'T') {
        crust = "Thin-Crust";
    } else if (aPizzaOrder.getHandThinDeep() == 'd' || aPizzaOrder.getHandThinDeep() == 'D') {
        crust = "Deep-Pan";
    }

    if (aPizzaOrder.getCheeseTopping()) {
        numberOfToppings += 1;
        toppings = toppings + "Additional Cheese ";
    }

Upvotes: 1

Views: 92

Answers (3)

sanjeevjha
sanjeevjha

Reputation: 1549

For such time of problem, we should we some design pattern and here Builder Pattern is best suited as below. I hope this will help you

package item2;

public class PizzaOrder {

    private String firstName;
    private int pizzaSizeInInches;    
    //add other fields

    private PizzaOrder(Builder builder){
        this.firstName=builder.firstName;
        this.pizzaSizeInInches=builder.pizzaSizeInInches;
        //set other fields
    }

    public static class Builder{
        private String firstName;
        private int pizzaSizeInInches;
        //add other fields

        public Builder(){
        }

        public Builder firstName(String firstName){
            this.firstName=firstName;
            return this;
        }

        public Builder pizzaSizeInInches(int pizzaSizeInInches) {
            this.pizzaSizeInInches = pizzaSizeInInches;
            return this;
        }

        //add other setter method like above

        public PizzaOrder build(){
            return new PizzaOrder(this);
        }          
    }

    public static Builder builder(){
        return new Builder();
    }

    public static void main(String args[]){
        PizzaOrder.builder()
                .firstName("sanjeev")
                .pizzaSizeInInches(10)
                .build();
    }
}

Upvotes: 0

c0der
c0der

Reputation: 18812

Basically you can consider three structures, and the combinations of them.
The first one is of course a constructor with a long list of variables :

public class Pizza {

    private String firstName, pizzaType;
    private String cheeseTopping, pepperoniTopping, sausageTopping;
    private int pizzaSizeInInches;

    public Pizza(String firstName, String pizzaType, String cheeseTopping, String pepperoniTopping,
            String sausageTopping, int pizzaSizeInInches) {
        this.firstName = firstName;
        this.pizzaType = pizzaType;
        this.cheeseTopping = cheeseTopping;
        this.pepperoniTopping = pepperoniTopping;
        this.sausageTopping = sausageTopping;
        this.pizzaSizeInInches = pizzaSizeInInches;
    }
}

The second basic structure is using setter methods for the long list of fields:

public class Pizza {

    private String firstName, pizzaType;
    private String cheeseTopping, pepperoniTopping, sausageTopping;
    private int pizzaSizeInInches;

    public Pizza() {};

    String getFirstName() { return firstName;}

    void setFirstName(String firstName) {this.firstName = firstName;}

    String getPizzaType() { return pizzaType;   }

    void setPizzaType(String pizzaType) {   this.pizzaType = pizzaType; }

    String getCheeseTopping() { return cheeseTopping;   }

    void setCheeseTopping(String cheeseTopping) {   this.cheeseTopping = cheeseTopping; }

    String getPepperoniTopping() {return pepperoniTopping;  }

    void setPepperoniTopping(String pepperoniTopping) { this.pepperoniTopping = pepperoniTopping;   }

    String getSausageTopping() { return sausageTopping; }

    void setSausageTopping(String sausageTopping) { this.sausageTopping = sausageTopping;}

    int getPizzaSizeInInches() {return pizzaSizeInInches; }

    void setPizzaSizeInInches(int pizzaSizeInInches) {  this.pizzaSizeInInches = pizzaSizeInInches; }
}

A side note : having the setter methods return this, for example :

Pizza setCheeseTopping(String cheeseTopping) {  
    this.cheeseTopping = cheeseTopping; 
    return this;
}

Pizza setPepperoniTopping(String pepperoniTopping) {    
        this.pepperoniTopping = pepperoniTopping;
        return this; 
}

makes it more convenient to invoke long list of setters by chaining them : pizza.setCheeseTopping("Melt").setPepperoniTopping("Hot");

A reasonable combination of the two above approaches is to have the constructor initialize the essential fields, and use setters for the optional fields, or those with a default value :

public class Pizza {

    private String firstName, pizzaType;
    private String cheeseTopping, pepperoniTopping, sausageTopping;
    private int pizzaSizeInInches;

    public Pizza(String firstName, String pizzaType) {
        this.firstName = firstName;
        this.pizzaType = pizzaType;
    }

    String getFirstName() { return firstName;}

    String getPizzaType() { return pizzaType;}

    String getCheeseTopping() { return cheeseTopping;   }

    Pizza setCheeseTopping(String cheeseTopping) {  
        this.cheeseTopping = cheeseTopping; 
        return this;
    }

    String getPepperoniTopping() {return pepperoniTopping;  }

    Pizza setPepperoniTopping(String pepperoniTopping) {    
        this.pepperoniTopping = pepperoniTopping;
        return this; 
    }

    String getSausageTopping() { return sausageTopping; }

    Pizza setSausageTopping(String sausageTopping) {
        this.sausageTopping = sausageTopping;
        return this;
    }

    int getPizzaSizeInInches() {return pizzaSizeInInches; }

    Pizza setPizzaSizeInInches(int pizzaSizeInInches) { 
        this.pizzaSizeInInches = pizzaSizeInInches; 
        return this;
    }
} 

A third approach for initializing long list of variables is to use the Builder Pattern :

public class Pizza {

    private String firstName, pizzaType, cheeseTopping, pepperoniTopping, sausageTopping;
    private int pizzaSizeInInches;

    public Pizza(PizzaBuilder builder) {
        this.firstName = builder.firstName;
        this.pizzaType = builder.pizzaType;
        this.pizzaSizeInInches = builder.pizzaSizeInInches;
        this.cheeseTopping = builder.cheeseTopping;
        this.pepperoniTopping = builder.pepperoniTopping;
        this.sausageTopping = builder.sausageTopping;
    }

    String getFirstName() { return firstName;}

    String getPizzaType() { return pizzaType;}

    String getCheeseTopping() { return cheeseTopping;   }

    String getPepperoniTopping() {return pepperoniTopping;  }

    String getSausageTopping() { return sausageTopping; }

    int getPizzaSizeInInches() {return pizzaSizeInInches; }

    static class PizzaBuilder {

        private String firstName, pizzaType;
        private String cheeseTopping, pepperoniTopping, sausageTopping;
        private int pizzaSizeInInches;

        PizzaBuilder setFirstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        PizzaBuilder setPizzaType(String pizzaType) {   
            this.pizzaType = pizzaType; 
            return this;
        }

        PizzaBuilder setPizzaSizeInInches(int pizzaSizeInInches) {  
            this.pizzaSizeInInches = pizzaSizeInInches; 
            return this;
        }

        PizzaBuilder setCheeseTopping(String cheeseTopping) {   
            this.cheeseTopping = cheeseTopping; 
            return this;
        }

        PizzaBuilder setPepperoniTopping(String pepperoniTopping) { 
            this.pepperoniTopping = pepperoniTopping;
            return this;
        }

        PizzaBuilder setSausageTopping(String sausageTopping) { 
            this.sausageTopping = sausageTopping;
            return this;
        }

        Pizza buid (){
            return new Pizza(this);
        }

    }

    //make new Pizza 
    public static void main(String[] args) {
        Pizza pizza = new PizzaBuilder().
                            setFirstName("Jack").setPizzaType("Annanas").
                            setPizzaSizeInInches(10).setCheeseTopping("Melt").
                            setPepperoniTopping("Hot").setSausageTopping("None").
                            buid();
    }
}

Upvotes: 0

CuriousMind
CuriousMind

Reputation: 3173

The general thumb rule is that the constructor should accept those arguments without which your object has no meaning. For e.g. Car is useless without an Engine. All the other attributes which are nice to have or add more features can be left as properties.

Besides that, you can also create a hierarchy of Classes with each having its own constructor detecting which properties must be mandatorily initialized. E.g. Base class is declared as Pizza which accepts size as an argument in constructor. Then you can have Cheez pizza derived from Pizza class, which accepts mandatory arguments to construct Cheez pizza.

Upvotes: 1

Related Questions