In Head First Design Patterns it teaches the strategy pattern by using a Duck example where different subclasses of Duck can be assigned a particular behavior at runtime. From my understanding the purpose of the strategy pattern is to change a single object's behavior at runtime, yet they are using inheritance of Duck to change the behavior of various types of Duck.

Strategy Pattern

Relevance?

Is context inheritance of Duck irrelevant to the strategy pattern or is varying Duck types and also varying their behaviors a good reason to employ the strategy pattern? Do situations where you need to vary both constitute a good reason to use strategy pattern? Why would they include this as the strategy pattern example?

A Simpler Example

Could I further simplify this example by just having a Duck class (no derived classes)? Then when implementing one duck object it can be assigned different behaviors based on certain circumstances that aren't dependent on its own object type. For example: FlyBehavior changes based on the weather or QuackBehavior changes based on the time of day or how hungry a duck is. I realize this would be solving a different problem than from the one in the book, but what I am looking for is a relevant strategy pattern example to fall back on.

Would my example above constitute the strategy pattern as well?

Edit:

I was successful in finding 2 simpler strategy pattern examples that adhere more strictly to being just strategy patterns without context inheritance: Hunter.java and solver.py.

有帮助吗?

解决方案

Yes, I think you are on the right track. The class using the strategy pattern does not have to be a subclass. The strategy pattern is an alternative to inheritance for code re-use. This comes back to the even broader comparison of inheritance vs composition.

From Design Patterns: Elements of Reusable OOP you would use strategy pattern to

  • Avoid an explosion of subclasses (due to combinations of behaviors)
  • If you need to swap out behavior at run-time

If you used inheritance to implement Quack and Fly behaviors you would result with all these subclasses to represent all the combinations of behaviors.

  • FlyableQuackableDuck
  • FlyableSqeakableDuck
  • FlyableMuteDuck
  • NoFlyQuackableDuck
  • NoFlySqueakableDuck
  • NoFlyMuteDuck

Having so many subclasses makes it harder to maintain which is why strategy pattern is favored in this case. You just need two properties which encapsulate Flyability and Quackability and you can mix and match these without creating new classes.

You also already mentioned the run-time benefit of if the weather changed the duck's Fly property could be replaced with a NoFly object due to the conditions.

This is consistent with the advice to favor composition over inheritance when possible.

其他提示

Could I further simplify this example by just having a Duck class (no derived classes)? Then when implementing one duck object it can be assigned different behaviors based on certain circumstances that aren't dependent on its own object type.

Certainly. For inspiration take a look in Head First Object-Oriented Analysis and Design. There's a "Rick's Guitars" showing an explosion of (musical) Instrument sub-classes. To remedy this all that varying behavior is wrapped in a "specification" class, observing the principle of encapsulate that which varies.

Abstract Factory - Context Based Construction

Here is the pattern. BTW, note that it uses strategy itself.

Focusing on concept, not implementation ... You might have a "WeatherFactory" that builds specification objects based on sunny or rainy, etc. conditions.

You could have "factories of factories" to get at constructing those "NoFlyInFogQuackableMallard" thingies. And indeed, this is what the Abstract Factory pattern is about. So perhaps a DuckFactory to make general duck-types, then a WeatherFactory to give it duck-type-specific foggy weather behavior.

许可以下: CC-BY-SA归因
scroll top