Reputation: 3485
As by design an enum constant in java is a singleton, and for sake of concurrent usage I normally create stateless enum instances and use method parameters to inject the data as needed.
Example:
Currently I am creating a REST service which has Operations (implemented as an enum using a variant of the strategy pattern).
public enum Operation {
DO_THIS() {
public Result doSomething(Object theData) {
}
} ,
// Other Operations go here
;
public abstract Result doSomething(Object theData);
}
Now I want to collect data about how often an operation has been called and how often it succeeded and the like.
I could save the state externally when using the enum instance but it rather seems that the state should be saved in the Operation as the operation should contain it's own state.
Now my general question is:
Is a stateful enum instance (besides from concurrency issues) a bad design?
Upvotes: 9
Views: 4052
Reputation: 6649
There is a case which would probably justify it. An enum can implement an interface, usually with the particular use case in mind which lets you create on runtime/openly "some other types of the enum class" in a dynamic fashion, to name it someway.
That means that enum "singleton" instances can be forced to implement some mutable-intended method signatures (as setters), which of course, you still can hide with an empty code or a NotSupportedException.
Luckily, final methods in an interface don't allow any possibility to change state. That would have been the sole "understandable" case I could come up with.
Upvotes: 0
Reputation: 782
A stateful enumeration is an oxymoron, even an anti-pattern!
http://en.wikipedia.org/wiki/Enumeration
An enumeration is a collection of items that is a complete, ordered listing of all of the items in that collection. The term is commonly used in mathematics and theoretical computer science to refer to a listing of all of the elements of a set. In statistics the term categorical variable is used rather than enumeration. The precise requirements for an enumeration (for example, whether the set must be finite, or whether the list is allowed to contain repetitions) depend on the branch of mathematics and the context in which one is working.
Enumerations have a finite number of values, which are supposed to be constant, which they are.
However, the fact that they are "first class" Java Objects totally goes against the grain of the intention or spirit of an enumeration.
If any kind of state is required, the enum (as mentioned earlier) should hold state in an Aspect or the offending enum, should at the very practical least, hold a reference to a delegate class holding state. Understanding "separation of concerns" will help.
Upvotes: 4
Reputation: 26876
I entirely agree with mparaz that it violates the Principle of Least Astonishment. People expect enums to be constants.
You can almost certainly work round the logging thing, by something like:
DO_THIS() {
public Result doSomething(Object theData) {
MyUtilClass.doSomething(Object theData);
}
}
and put your logging in the other class.
HOWEVER if you can't work round this, the Principle of Least Astonishment is a guideline; you can violate it PROVIDED you give users of the class enough warnings about what is going on. Make sure the Enum declaration contains a BIG notice saying that it is mutable, and describing exactly what the mutability is. The Enum should still work; it's doing reference comparison against to single instance to test enum values.
Upvotes: 1
Reputation: 147164
Any form of mutable static is a sin. (Well, you might get away with non-leaky caches, some lazy initialisation and forms of logging.)
Upvotes: 4
Reputation: 625237
Yes. And by 'yes' I mean 'Always'.
If you want to collate stats on the number of operations called, implement some observability.
Upvotes: 7
Reputation: 45398
This seems like a bad use for enums - why not just go with a base abstract class with a new subclass for each operation?
Upvotes: 1
Reputation: 2069
I think it violates the Principle of Least Astonishment.
People expect the common usage of enums as they were originally designed - as constants or tokens, and not as general purpose classes with state.
Upvotes: 19