State Pattern – should a state know about its context

design-patterns

I am referring to the state pattern as described in this link.

In the example class diagram, a context has numerous states. However, it does not show how does a state communicates with a context (perhaps an input in a state has impact on a setting in the context).

The two examples on the page shows either passing the context to the state via a function, or storing a reference to the context. Are those advisable?

Are there other ways for a state to communicate with a context?


Update to an edit:

For instance, I am doing a remote control which can have several states. Say, the context has a setting for Volume, and I am in one of the states which allow me to tweak the volume. How should the state communicates with the context that the volume is being changed?

Best Answer

That's one of the most complicated and apparently pointless design patterns I've come across. It very tightly couples the components in a way that would make change or extensibility difficult.

In that link, the example shows a bank account class whose behaviour changes depending on the available balance. The behaviour is changed by assigning completely new types to the account 'state' object, except each 'state' is responsible for assigning each other to an account. The control flow is not clear; simply calling 'account.deposit' ends up reassigning internal members to new classes.

When a new rule is invented (e.g; we include a 'platinum' account, which simply has a higher interest rate); we now have to modify 4 classes; 3 x existing state types and the original account, plus create a completely new implementation of 'state' which needs to fully implement the behaviours of a bank account, simply to alter one 'rule'.

There might be a good case to use this pattern intentionally, but that doesn't seem to be it, to me.

And I cannot see how you could sensibly apply this pattern to the concept of a remote control. A remote control has no state (apart from perhaps on/off), it simply sends instructions to another device. That device may have a state (e.g; volume is maxed) in which case a particular instruction could be ignored (cannot increase volume when maxed) but you'd be massively over-engineering the solution trying to squeeze it into this pattern.