State and Proxy: Substitution Proxy
I was reading the State pattern in GoF and there was one issue they addressed that I think I have a better solution for.
A quick reminder if you don’t remember the pattern: Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. The example GoF gives is a TCPConnection class that is composed of a TCPState, the TCPstate will behave differently depending on the current state of the connection (such as throwing an exception if close() is called when the state is already “closed”). The pattern consists of a Context (TCPConnection), State (Abstract interface for the different states), along with ConcreteStates being subclasses of State.
The issue I mentioned earlier regards where the state transition logic resides. GoF describes two possible solutions; either Context will keep track of all possible states and toggle when it sees fit, or the ConcreteStates will keep track of their successing states and the conditions for changes.
I don’t fancy either of these solutions. Giving Context the responsibility will force it to tightly couple to all the ConcreteStates. I also suggest that the conditions for state changes should be none of its business, giving it a simple interface and little to worry about. On the other end, we give ConcreteStrategy more responsibility. I see no problem with this per se, but in order to make sure that Context sees the changes all ConcreteStates must store a reference to the Context, and set its state property whenever a transition is made. I find this to be even worse since State is clearly on a level below Context and should not have to depend on it. It also couples the classes too tightly.
So, we want Context to easily be able to access the current state, not having to worry about what might happen later, and we don’t want State to be aware of Context. I immediately thought of the Proxy pattern for this task. If a proxy is placed between the Context and the States it can be responsible for transitions whenever necessary. All Context has to do is call the usual methods on the proxy, and State needs only perform the operations that Proxy relays.
It turns out that GoF only defines Proxies as residing between two objects, but the pattern I described seems so closely related to a Proxy that I’m going to go ahead and call it a Substitution Proxy. What we end up with is then a mixture of the two patterns. Though it could be that the Substitution Proxy doesn’t use several different ConcreteState classes but instead instantiates several instances of the same class and therafter toggles between those in some fashion.
On top of my head I can’t think of any situation that it would not make sense to use State with Substitution Proxy over a plain State, but perhaps someone else could think of some downsides.
Post new comment