Although you could use reflection (ie the dark arts), you can do it with minimal code if all shapes have the same constructor signature of say List<Double>
(which includes integers like your example):
private static Map<String, Function<List<Double>, Shape>> factories =
Map.of("Circle", Circle::new, "Rectangle", Rectangle::new); // etc
public static Shape createShape(String input) {
String[] parts = input.split(" ");
String name = parts[0];
List<Double> dimensions = Arrays.stream(parts)
.skip(1) // skip the name
.map(Double::parseDouble) // convert String terms to doubles
.collect(toList());
return factories.get(name).apply(dimensions); // call constructor
}
interface Shape {
double getPerimeter();
}
static class Rectangle implements Shape {
private double height;
private double width;
public Rectangle(List<Double> dimensions) {
height = dimensions.get(0);
width = dimensions.get(1);
}
@Override
public double getPerimeter() {
return 2 * (height + width);
}
}
static class Circle implements Shape {
double radius;
public Circle(List<Double> dimensions) {
radius = dimensions.get(0);
}
@Override
public double getPerimeter() {
return (double) Math.PI * radius * radius;
}
}