Must a class that is a "gang of four" strategy be completely stateless (ie no fields) or can it contain immutable state (ie final f开发者_如何学Cields)?
A strategy class encapsulates an action, not a thing. So although you could if you really had to, it wouldn't make a lot of sense to keep state in it. Think of it as a verb, not a noun. Or at least as a noun that describes an action. On the other hand, you could always parametrize the strategy and pass the state of the client object to it by method call or similar.
Also, whether a class is stateless or statefull doesn't really depend on the final
keyword on its fields. Examples:
- When used on objects
final
only means that the reference to an object may not be changed. You can still change the contents of that object, like its fields. In that case, your class is statefull although its field is final. - If the field really is a constant, then for most intents and purposes you can consider it stateless. For example, you can declare a field
private static final
and then make sure you never do anything to change the state of the referenced object.
EDIT: Let's try to distinguish between parameters of strategy itself and parameters of one particular execution of that strategy. If the strategy class is stateless then there is no point in having more than one instance of that class, which makes the object, not the class, represent the action itself and a method execution represent one particular execution of that strategy.
Now, if we have a parameter of the strategy itself it only makes sense that the parameter has the same value for all executions of that strategy. So, it can be placed in a constant, method call that returns a constant (if we don't wan't static stuff), or even hardcoded. As explained above, that can be implemented in the stateless way.
On the other hand, if the parameter describes one particular execution of the strategy, then just pass it as a parameter to the method. It will do.
Additional note: There is a good reason to use action objects with 'adverbs' packed in its state if we want to, say, have some kind of action queue of execution with delay, scheduling... There's a pattern for that too - Command.
No, why should it be stateless? The strategy could be anything, it simply represents some runtime pluggable unit of functionality that allows you to extend the modify the behaviour of the consuming class. There is nothing, as far as I know, that suggests the requirement of statelessness, nor immutability.
Statelessness refers to the fact that no data is preserved between runs of a strategy; i.e. if you execute the same strategy twice, nothing from the previous run of the strategy would carry over. This is beneficial in that it saves you the trouble of having to "reset" your Strategy implementations when needed.
Note that in the description of the Strategy pattern implementation they make reference to a Context (@ page 317 in my book) that contains the data the strategy needs to execute. All the 'state' required by the implementations should probably go in these context objects.
This means that the strategy implementations themselves are stateless, but the pattern as a whole has state as the required data is passed around in a context.
For example, if you had strategy implementations for mathematical operations, there are at least 2 ways to do it. The first would be to set arg1 and arg2 (and 3, and 4...) on the strategy implementations when you construct them. Then when you execute the implementation would grab its fields and do the operation. The problem is, if you run the same implementation again, you have to reset all its fields (or create a new implementation).
The second way would be to create a context that contains all the arguments. The stategy implementations would grab the values it needs off the context. Then you could reuse each instance of your strategy implementation, just passing a new context each time. No worry about recreating new instances of the implementations, or forgetting to reset the implementation instance. Of course, you still need to manage the contexts correctly.
The intent of the strategy pattern is to work on the strategy method arguments directly in the method local scope. The strategy class itself can of course hold some fields whenever required, but the method arguments should in no way be assigned to those fields as it can introduce threadsafety problems if the strategy object is used more than once.
Yes, as this is algorithm chooser mostly. Concrete algorithm can have state, but not the chooser.
By the way in this strategy we don't have one class. Which concrete class do you mean? In what role?
精彩评论