I've been looking at the state pattern today, with the goal of allowing business entities to behave differently depending on their state. So, an Order in "Shipped" state would have a completely different behavior to an order in "Placed" state; I might not be able to update an order in Shipped state, but I could if it were merely "Placed".
In Design Patterns [GOF], the intent of State is this:
Allow an object to alter its behaviour when its internal state changes. The object will appear to change class
Perfect. But, when I had a crack at implementing it, I got a bit peeved. Here's a few reasons why:
Too many classes; An order entity with states Draft, Raised, Packed, Shipped and InQuery would require 7 classes: One for the context, one for state base class, and one each for the states themselves. This doesn't feel right to me.
Violation of DRY? I'm repeating the interface declarations several times over. If I weren't using this pattern, I'd have only 1 class. I'm just not sure that, in my simple cases at least, the extra conceptual baggage is worth it.
Lack of cohesion. The context is delegating to the various states, and in turn each of those states contains business rules. Would it be better to keep all business logic in one place, or is State an elegant variation of the "rule object" pattern and in fact more cohesive?
Lack of real-world use. I don't see the State pattern used that much, certainly nowhere near as much as Singleton, Strategy, Factory, Iterator, Mediator, Observer and many others. I tried a brief .NET Reflector search, but couldn't find one use of this pattern in the .NET framework. A google code search came up with more possible uses.
Before I get slammed for this post, I am smart enough to see some good things about the State pattern:
- I like the fact that it uses composition over inheritance to handle state-specific behaviour.
- I like the fact that the pattern makes states a first class citizen, that's explicit.
- I also like the fact that individual states are testable.
- There's a hint of OCP here, you can add more states (extend the class) without modifying it.
I must admit, I'm not really qualified to GOF bash :) And, I haven't got the experience with this pattern to truly say I don't like it. However, I would like to find a way of implementing the state pattern in c# so that:
- Entities can only transition to allowable states
- You can have different behaviors in each state
- You don't need to create lots of classes
- You can keep business rules in one place Entity
- It feels natural!
Any thoughts?