Reputation: 3968
I am currently doing some code refactoring. So I came up replacing an existing inheritance
design by a decorator
design. But I am struggling with multiple generics (maybe it is simply not possible).
I have the above design at the moment. There is the IConstraint
which check
s a class against an implemented constraint. The concrete realization of those constraints are SimpleConstraintA
and SimpleConstraintB
both of them are checking some values from ClassA
. The Decorator
enhances the constraints e.g. there are some constraints which should not be checked when a specified value is not in range. ClassA
implements the interfaces IA
and IB
so thatDecoratorA
and DecoratorB
can work with it.
The usage of the design is as followed:
Test classToCheck = new Test("test");
IConstraint<Test> constraint = new DecoratorA<>(new DecoratorB<>(new SimpleConstraint()));
boolean value = constraint.check(classToCheck);
So what I want is to use the code with a different number of input parameters and different types. Like:
Test classToCheckA = new Test("testA");
Test classToCheckB = new Test("testB");
IConstraint<Test> constraint = new DecoratorA<>(new DecoratorB<>(new SimpleConstraint()));
boolean value = constraint.check(classToCheckA, classToCheckB);
Or:
Test classToCheckA = new Test("testA");
// TestB does implement the same interfaces as Test
TestB classToCheckB = new TestB("testB");
IConstraint<Test> constraint = new DecoratorA<>(new DecoratorB<>(new SimpleConstraint()));
boolean value = constraint.check(classToCheckA, classToCheckB);
Or:
Test classToCheckA = new Test("testA");
// TestB does implement the same interfaces as Test
TestB classToCheckB = new TestB("testB");
// TestC does implement the same interfaces as Test
TestC classToCheckC = new TestC("testC");
IConstraint<Test> constraint = new DecoratorA<>(new DecoratorB<>(new SimpleConstraint()));
boolean value = constraint.check(classToCheckA, classToCheckB, classToCheckC);
I tried using varargs
, Lists
or Object[]
instead of the T
from the check(obj:T)
but then I always need casts and a lot of exception handling (e.g. the number of input parameter need to be correct), so I was not satisfied.
The following code is one example what I tried. Like you see in the SimpleConstraint
the check
method only the type (Test
) is allowed.
public interface IConstraint<T extends ICheckable> {
public boolean check(T[] checkable);
}
public class SimpleConstraint implements IConstraint<Test> {
@Override
public boolean check(Test[] checkable) {
return true;
}
}
This is not possible with the above code:
Test classToCheckA = new Test("testA");
// TestB does implement the same interfaces as Test
TestB classToCheckB = new TestB("testB");
IConstraint<Test> constraint = new DecoratorA<>(new DecoratorB<>(new SimpleConstraint()));
boolean value = constraint.check(classToCheckA, classToCheckB);
Is there some improvement of the design so that different number of input parameters and different types can be supported?
Upvotes: 1
Views: 1564
Reputation: 10549
In the code above, the problem is, that Test and TestB does not have common ancestor...
IConstraint<Test> constraint = ...
boolean value = constraint.check(classToCheckA, classToCheckB);
You can make that work if TestB extends Test
or other way around.
Better approach would be to have
IConstraint<ICheckable> constraint =
Upvotes: 2