Premise
Existing codebase (not likely to change):
public interface Thing {
void doSomething();
}
And with the implementations such as (ThingA, ThingB, ThingN, etc):
public final class ThingA implements Thing {
private final ThingAInput input;
public ThingA(ThingAInput input) {
this.input = input;
}
@Override
public void doSomething() { ... }
}
ThingAInput
, ThingBInput
, and ThingNInput
are NOT related at all (disjoint types).
Problem
Input objects can be very complex and I want users to create a class that encapsulates their own business logic. I explored two approaches, but they were both clunky and that leads me to think if I am approaching the problem incorrectly and there is a better way to use Java.
Option 1
I thought about defining a generic interface:
public interface ThingInput<T> {
T getInput();
}
User can then create:
public final class MyThingInput<ThingBInput> {
private final ThingDep thingDep;
@Inject
MyThingInput(ThingDep thingDep) {
this.thingDep = thingDep;
}
@Override
public ThingBInput getInput() {
return createThingAInput(thingDep);
}
// ... very complex business logic ...
private static ThingAInput createThingAInput(ThingDep dep) {
// returns a ThingAInput
}
}
then use a ThingFactory to create the correct instance based on type. But I am unable to say ThingInput<ThingAInput | ThingBInput>
and enforcing this behavior requires runtime checks.
Option 2
I could use inheritance on Thing
directly:
public abstract class AbstractThing implements Thing {
protected final Thing thingImpl;
public AbstractThing(ThingAInput input) {
this.thingImpl = new ThingA(input);
}
public AbstractThing(ThingBInput input) {
this.thingImpl = new ThingB(input);
}
// Proxies doSomething to the underlying impl.
@Override
public void doSomething() {
return ThingImpl.doSomething();
}
}
and users can create:
public final MyThingA extends AbstractThing {
@Inject
MyThingA(ThingDep thingDep) {
super(createThingAInput(thingDep));
}
// ... very complex business logic ...
private static ThingAInput createThingAInput(ThingDep dep) {
// returns a ThingAInput
}
}
Aucun commentaire:
Enregistrer un commentaire