wake-0
wake-0

Reputation: 3968

Decorator Pattern with multiple generics

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).

Decorator implementation

I have the above design at the moment. There is the IConstraint which checks 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

Answers (1)

Betlista
Betlista

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

Related Questions