Reputation: 4609
I have an abstract class in my application (let's call it BaseRule
).
BaseRule
implements the Comparable
interface, and contains an abstract method signature public abstract int getExecOrder()
.
Within the BaseRule
implementation of the compareTo()
method in the BaseRule
class, the return value of getExecOrder()
is used to compare the objects.
At present, I have 3 concrete implementations of the BaseRule
class, each of which implement the getExecOrder()
method
The ultimate purpose of having the BaseRule
class implement the Comparable
interface is that a Collection of BaseRule
objects are passed to a utility that needs to sort these objects to ensure that they are executed in the proper order.
In this case, execution order only matters at the Class level, meaning that every BaseRuleA
must be executed before any BaseRuleB
is executed, but every BaseRuleB
is effectively 'equal' to every other BaseRuleB
, so the order that those BaseRuleB
objects are processed does not matter
My question is, is there a better way to handle comparing these objects as opposed to using (what I came up with) a getExecOrder()
method ?
Right now, I only have 3 concrete implementations of BaseRule
so it was easy enough to just assign return values of 1,2,3 to those getExecOrder()
method calls, but if another developer adds a new BaseRule
implementation, they would have to scan all the existing implementations, and (possibly) update those return values in all of the classes to accommodate the new BaseRule
.
Any ideas on a better implementation?
Upvotes: 0
Views: 2409
Reputation: 715
I honestly think your proposed implementation is the best way to go about this. Definitely add some comments to the abstract getExecOrder()
so that future developers know exactly what their implementation of it is supposed to do.
Upvotes: 1
Reputation: 44150
I guess you're talking about the following sort of thing?
abstract class BaseRule implements Comparable<BaseRule>
{
abstract int executionPrecedence();
@Override
public int compareTo(final BaseRule that)
{
return Integer.compare(this.executionPrecedence(), that.executionPrecedence());
}
}
class RuleA extends BaseRule
{
@Override
int executionPrecedence() { return 0; }
}
class RuleB extends BaseRule
{
@Override
int executionPrecedence() { return 1; }
}
It seems fairly reasonable. If you're concerned about having to change the values of existing classes in the future then just leave big gaps rather than using contiguous integers.
A = 10000
B = 20000
C = 30000
Now you have 9999 spaces to place future implementations between these ones.
Maybe also add a unit test which uses reflection to check that no two implementations share the same precedence.
Upvotes: 5