The Problem
switch (choice) {
case 0:
return new Class0();
case 1:
return new Class1();
case 2:
return new Class2();
case <n - 1>:
return new Class<n - 1>();
default
return new Class<n>();
}
What I Tried
Chain of responsibility design pattern. A great and amazing solution for distributing complex tasks. However, I don't want a class that checks if it can do 1 method.
Motivation
I'm tired of updating the code every time I add something. Bad design.
CodePudding user response:
Providing that each of Class0, Class1, ...ClassN
have public non-arg constructor, Class::forName
and Class::newInstance
may be used to build a class name, retrieve a class, and instantiate it:
public static final int MAX_CLASS_N = 5; // n limit
public Object getInstance(int x) throws Exception {
int id = x < 0 || x >= MAX_CLASS_N ? MAX_CLASS_N : x;
return Class.forName("Class" id).newInstance();
}
Similarly, an array/list of Class
can be created as a "cache", a helper method replacing a checked ClassNotFound
exception with a runtime IllegalArgumentException
is needed:
public static Class<?> classForName(String clazz) {
try {
return Class.forName(clazz);
} catch (ClassNotFoundException cex) {
throw new IllegalArgumentException("Bad class name: " clazz, cex);
}
}
public static final Class[] BUILDERS = IntStream.rangeClosed(0, MAX_CLASS_N)
.mapToObj(i -> "Class" i)
.map(MyClass::classForName)
.toArray(Class[]::new);
public static Object buildInstance(int n) throws Exception {
int id = n < 0 || n >= MAX_CLASS_N ? MAX_CLASS_N : n;
return BUILDERS[id].newInstance();
}
Tests (assuming classes Class0, Class1, ... Class5
are defined)
System.out.println(getInstance(-1));
System.out.println(getInstance(2));
System.out.println(getInstance(5));
System.out.println("----");
System.out.println(buildInstance(0));
System.out.println(buildInstance(3));
System.out.println(buildInstance(50));
Output:
Class5@445b84c0
Class2@61a52fbd
Class5@233c0b17
----
Class0@63d4e2ba
Class3@7bb11784
Class5@33a10788
CodePudding user response:
In this example we use instead of the switch expression an enum representing the implementing a class supplier:
interface ProblemSolver{}
public enum Choice implements Supplier<ProblemSolver> {
ONE(AnyProblemSolver::new),
TWO(AnyProblemSolver::new)
;
private final Supplier<ProblemSolver> supplier;
Choice(Supplier<ProblemSolver> supplier){
this.supplier = supplier;
}
@Override
public ProblemSolver get() {
return supplier.get();
}
}
public ProblemSolver getProblemSolver(Choice choice){
return choice.get();
}