简体   繁体   中英

Decide what constructor call based on user input

I would need to ask the user how many sides has the Figure he wants to draw, then call the right constructor to instantiate the object.

Below is my attempt to solve the answer using IF statements (or I could have used a switch) , but I don't know if it's the best way to do this, possibly with Java inheritance and polymorphism.

All the classes extends the class Figure.

CLASSES DIAGRAM:

      --------------- Figure ---------------
      ^         ^             ^            ^
      |         |             |            |
      |         |             |            |
   Circle    Triangle      Rectangle     Exagone

MAIN CLASS:

import java.util.Scanner;

class Draw {

   static void main(String[] args){

       Scanner userInput = new Scanner(System.in);
       int num_sides;

       //user input
       System.out.println("How many sides has the figure you want to draw?");   
       num_sides = userInput.nextInt();


       //---> deciding what constructor to call with if statements

       if(num_sides == 0){
          Figure f1 = new Circle();
       }
       else if(num_sides == 3){
          Figure f1 = new Triangle(); 
       }
       //...
       else{
          System.out.println("Error. Invalid sides number");
       }


   }
}

CLASSES CODE:

class Figure{

    private int sides;

    public Figure(int num_sides){
       sides = num_sides;
    }
}


class Circle extends Figure{

   public Circle(){
      super(0);
   }

}

//... all the other classes has the same structure of Circle

Factory Methods

Have you considered the Factory Method Pattern ? Basically, you have a method that's something like this:

public Figure createInstance(int numSides) {
    Figure figure = null;

    switch(numSides) {
    case 0:
        figure = new Circle();
        break;
    case 3:
        // etc...
        // Make a case for each valid number of sides
        // Don't forget to put a "break;" after each case!
    default:
        // Not a valid shape; print your error message
    }
    return figure;
}

And let that factory method do the deciding instead.

This is a very good example of when to use the factory design method . The standard is to have a factory class that figures out what constructor to call, and then returns that object. Personally, I tend to shove it into a static method of the base class (feel free to comment why this is possibly bad).

One way to solve this would be to add a factory method to your Figure class to construct other figures. This would keep the code in one place and would make it easy to use for Figure's clients.

class Figure{

    private int sides;

    /* package */ Figure(int num_sides){
        sides = num_sides;
    }

    public static Figure createFigure(int num_sides) {
        if (num_sides == 0) {
            return new Circle();
        } else if (num_sides == 4) {
            return new Square();
        }
        throw new IllegalArgumentException("Invalid number of sides");
    }
}


class Circle extends Figure{

    public Circle(){
        super(0);
    }

}

class Square extends Figure{

    public Square(){
        super(4);
    }

}

The IFs you use are not nested, an example for nested if would be:

if(condition1) {
    if(con2)
        //body
}

Performance-wise it would be generally better to use: switch-case. Since here you don't have so many cases an else if would do the trick, but know that because of the JVM the switch is more efficient with more cases.

I would use the Factory design pattern as suggested, but I would also make a generic constructor in the case that the number of sides > 0 with the number of sides as an argument. Think about it: You could just divide 360 degrees or 2 PI rad by the number of sides and have your corners plotted on a virtual circle. Reuse your code and make all possible numbers of sides possible, with the notable exception of 0 for a circle.

Your approach suggests you have one class with a property that determines the number of sides of the figure to be created rather than a separate class for each figure. Then it would make sense to ask the user for the number of sides, you could pass the number to your class Multigon's constructor and be done with it. This seems to be the better model because there is no specialization or extension to be considered, just a varying amount. Your figures are all of the same class, they all go round in a number of steps in a continuous manner. A rake would be a different class, as would be a cross.

Furthermore I would argue a circle has one side. A line has two (to be drawn forth and back) and the next one would be the triangle. Zero would be a dot.

But to answer your question, a switch statement would be nicer than an if. After all, you want to handle cases, not conditions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM