Don't get into a state about changing a pattern

This article was originally published in VSJ, which is now part of Developer Fusion.
One of the simplest applications that you can write for Windows is a doodling application, along the lines (no pun intended) of that shown in Figure 1. In fact, many MFC developers grew up learning how to write Windows applications by working through the (infamous) Scribble sample.

Figure 1
Figure 1: WPF Scribble in action

Now don’t worry; there’s no MFC code in this article. Instead, and as part of my series of articles on Design Patterns, I’m going to use a Windows Presentation Foundation version of Scribble to highlight one crucial point about patterns: be prepared to adapt them to suit your requirements. Along the way, we’ll also take a quick sideways glance at a new feature introduced with .NET 3.0: dependency properties.

Getting started

If we exclude the use of WPF’s extensive support for ink input, which would somewhat trivialise the exercise, you can imagine that implementing the main user interactions for a simple Scribble application can be accomplished by:
  1. Placing a Canvas into the Window for the user to draw on
  2. Handling the Canvas’ MouseLeftButtonDown event to start a line
  3. Handling the MouseMove event to add points to the line, but only when the mouse’s left button is down
  4. Handling the MouseLeftButtonUp event to complete the line
  5. Dealing with any mouse capture issues
You might have noticed the emphasis in the third bullet point. To express this succinctly, the Canvas operates in two states: one in which moving the mouse has no effect, and a second in which lines are drawn while the user holds down the left mouse button. The triggers that switch between these two states are the user pressing and then releasing the left mouse button. This behaviour is highlighted in the simplified state diagram shown in Figure 2.

Figure 2
Figure 2: State diagram for the ScribbleCanvas

It’s fairly easy to visualise additional states that might be introduced as the Scribble program evolves to include features such as selecting lines (perhaps to copy or delete them), dragging ‘n’ dropping lines and even adding features such as text input and drawing shapes; although at this point Scribble starts to transition into Paint, and one has to question whether spec-creep has finally set in!

If we aren’t careful, as new features and interactions are added we might end up with a code base that is littered with conditional blocks that are similar to:

...
enum State
{
	Default,
	DrawingLine,
	DraggingObject,
	DraggingSelectionRectangle,
	...
}
public class ScribbleCanvas : Canvas
{
	// The state of the canvas expressed as an enum
	State _currentState = State.Default;
	protected override void OnMouseMove( MouseEventArgs e )
	{
		base.OnMouseMove( e );
		switch( _currentState )
		{
			case State.DrawingLine:
// Code to add a new point to the line
				break;
			case State.DraggingObject:
// Code to drag the object
				break;
			case State.DraggingSelectionRectangle:
// Code to select objects
				break;
			...
		}
	}
}
The code above, or something very similar to it, is likely to be replicated in many different event handlers. This will rapidly become sub-optimal from both the maintenance and debugging perspectives, and hence it should be avoided if possible. It is clear, therefore, that should we want to isolate ourselves from such smelly code, it makes sense to factor the mouse handling logic out into a separate set of classes. This will allow us to merely slide in an appropriate object to handle the events depending on the current state of the canvas. In other words, we’re going to want to implement the Gang of Four’s State pattern.

Introducing the State pattern

The State Pattern is summarised by the GoF as follows:
State: allow an object to alter its behaviour when its internal state changes. The object will appear to change its class.”
Further delving into the documentation reveals that the State pattern becomes applicable when operations start to gain “multipart conditional statements that depend on the object’s state”. This certainly sounds like it’s going to be of benefit in our scenario, given that we are likely to add ever more complex mouse handling as we add features. In fact, a good litmus test of whether State pattern should be used is when you discover enum or integer fields in your classes that indicate which state the object is currently in.

Figure 3
Figure 3 shows the standard UML diagram for the State pattern

By examining Figure 3 we can see that we expect the object that will change its behaviour – the drawing canvas for our Scribble application – to be composed with a specific implementation of the “State” type. The canvas will internally flip between the states in response to certain stimuli, such as the left mouse button being pressed, without the client caring or being aware.

It is this change to the internal state that gives the appearance that the object is changing its type, and it is this behaviour that ultimately defines the State pattern.

However, Figure 3 seems to imply that there is a common interface that all of the concrete state types must implement (through inheritance), and that it is via this interface that the object will delegate method calls to the currently composed state object. Unfortunately, in our case it’s quite clear that the different state objects will need to respond to different sets of events.

New (and as yet unspecified) states might also want to handle events from the keyboard or stylus. Clearly, we could add handlers for all known events to the State base class/interface, but this would be tedious, redundant in most cases and might introduce considerable re-testing work in the case that new events are added to the system.

So does this preclude the use of the State Pattern where the state objects will be handling events? Not at all, so long as you’re prepared to tweak the pattern a little bit. This is, in fact, one of the most important aspects of working with patterns: you must be prepared to adapt them to your needs, rather than be totally constrained by them.

Adapting the State Pattern to meet our requirements

So how do we adapt the State Pattern to work when we want each of the State-derived types to expose potentially completely different functionality?

The first thing to realise is that the client will not (in this case) be calling methods that are delegated across to the state object. Instead, the state objects are simply going to be responding to events that are raised as a result of user interactions with the canvas. Consequently, these state objects need to both connect their event handlers when they become active and disconnect them when they become inactive. This last statement is particularly important, because failing to disconnect the event handlers will:

  1. Result in multiple event handlers being called, resulting in chaotic behaviour, and
  2. Leave extant references to the state objects (via the delegate object that is connected to the event), thus preventing a “discarded” state object from being collected
Therefore, rather than have the base class define the methods that will be called by the canvas, it merely defines methods that will be called when the state object is connected and disconnected to/from the canvas. Figure 4 shows the class diagram for a simple implementation.

Figure 4
Figure 4: Implementing the State pattern for the ScribbleCanvas

There are a few things to note from this diagram:

  1. The ScribbleCanvas class has a State property that holds a reference to the current state, which is of type CanvasState. The functionality of the ScribbleCanvas will be altered by setting this State property to one of the CanvasState-derived objects.
  2. The concrete classes DefaultState and LineDrawingState contain the event handlers that are required for the particular state that the canvas finds itself in. Each type is free to handle whichever events are appropriate to its functionality.
  3. The CanvasState abstract class does not define or implement any event handling methods itself. Instead, it just has two methods that are used to connect and disconnect event handlers as necessary. We’ll examine when and how these are used in just a moment.
  4. The CanvasState class defines a property that enables any derived type to reference the ScribbleCanvas for which it’s providing the state behaviour. There is a negative consequence of this approach, as it introduces a level of coupling that doesn’t exist in the standard State pattern.
So let’s take a look at the code that underpins the diagram.

The CanvasState types

The CanvasState-derived types provide the event handling logic for the user’s interactions with the canvas.

Obviously, it’s important that the event handlers are connected when the state object is hooked up to the canvas but, as has been mentioned, it’s just as important that the handlers are removed when the state object is no longer being used.

This is the purpose of the AddHandlers() and RemoveHandlers() methods, as shown here:

internal abstract class CanvasState
{
	private ScribbleCanvas _canvas;
		internal CanvasState( ScribbleCanvas canvas )
	{
		_canvas = canvas;
	}
	
	protected ScribbleCanvas Canvas
	{
		get { return _canvas; }
	}
	
	internal virtual void RemoveHandlers() {}
	internal virtual void AttachHandlers() {}
}

internal class DefaultState : CanvasState
{
	internal DefaultState( ScribbleCanvas canvas )
		: base( canvas ) {}

	internal override void AttachHandlers()
	{
		Canvas.MouseLeftButtonDown +=
			HandleLeftButtonDown;
	}

	internal override void RemoveHandlers()
	{
		Canvas.MouseLeftButtonDown -=
			HandleLeftButtonDown;
	}

	private void HandleLeftButtonDown(
		object sender, MouseButtonEventArgs e )
	{
		Canvas.State = new LineDrawingState(
				Canvas, e.GetPosition( Canvas ) );
	}
}

internal class LineDrawingState : CanvasState
{
	internal LineDrawingState( ScribbleCanvas canvas,
		Point startPoint ) : base( canvas )
	{
		// Code to start the line
		...
	}

	internal override void AttachHandlers()
	{
		Canvas.MouseLeftButtonUp += HandleLeftButtonUp ;
		Canvas.LostMouseCapture += HandleLostCapture;
		Canvas.MouseMove += HandleMouseMove;
	}

	internal override void RemoveHandlers()
	{
		Canvas.MouseLeftButtonUp -= HandleLeftButtonUp;
		Canvas.LostMouseCapture -= HandleLostCapture;
		Canvas.MouseMove -= HandleMouseMove;
	}
	
	void HandleLeftButtonUp(
		object sender, MouseButtonEventArgs e )
	{
		// code to complete the drawing of the line
		...
		ChangeState();
	}
	
	void HandleLostCapture( object sender, EventArgs e )
	{
		ChangeState();
	}
	
	void HandleMouseMove( object sender, MouseEventArgs e )
	{
		// Code for creating points for the line	
		...
	}

	void ChangeState()
	{
		Canvas.State = new DefaultState( Canvas );
	}
}
Each of the concrete implementation types uses the AddHandlers() and RemoveHandlers() methods to connect and disconnect its event handling methods. In the case of the DefaultState class, it handles the MouseLeftButtonDown event and uses this to set the canvas’ State so that it is using a LineDrawingState object.

Similarly, the LineDrawingState returns the favour and resets the canvas back to its default state when either the left mouse button is released or should the mouse capture be lost.

So how and when do the AddHandlers() and RemoveHandlers() method get called? For that, we need to delve into the code for the ScribbleCanvas class.

The ScribbleCanvas class

The listing below contains the relevant code for the ScribbleCanvas class:
public class ScribbleCanvas : Canvas
{
	public static DependencyProperty StateProperty;

	static void StatePropertyChanged( DependencyObject canvas,
		DependencyPropertyChangedEventArgs e )
	{
		// Disconnect event handlers from the current state
		if( e.OldValue != null ) ((CanvasState) e.OldValue).RemoveHandlers();
			
		// Connect event handlers for the new state
		if( e.NewValue != null ) ((CanvasState)e.NewValue).AttachHandlers();
	}
		
	static ScribbleCanvas()
	{
		FrameworkPropertyMetadata fpm = new FrameworkPropertyMetadata(
				StatePropertyChanged );
		StateProperty = DependencyProperty.Register(“State”,
				typeof( CanvasState ), typeof( ScribbleCanvas ), fpm );
	}
	
	public ScribbleCanvas()
	{
		this.State = new DefaultState( this );
	}

	public CanvasState State
	{
		get
		{
			return (CanvasState) base.GetValue( StateProperty );
		}
		set
		{
			base.SetValue( StateProperty, value );
		}
	}
	// other code elided for clarity
	...
}
This code might look a bit strange if you’ve not been using .NET Framework 3.0, as it relies on a new feature designed to extend the standard .NET property mechanism: dependency properties. Let’s take a quick look at them now.

Dependency properties

Dependency properties were introduced to reduce the memory requirements of objects that have lots of properties, as well as to support additional features such as providing a default value for the property, value coercion, data binding, value “inheritance” from a parent object in a tree, styling and themes, and animation. In addition to all of these features, dependency properties also support property change notification, more on which in a moment.

As shown in the ScribbleCanvas listing above, it’s normally a good idea to wrap a dependency property with a matching standard .NET property, as this simplifies setting the value of the property from code. However, there is one critical thing to remember: the get and set blocks should contain no code other than that to retrieve the value from, or store the value into, the dependency property. This is because data binding and other WPF features will interact directly with the dependency property and will not access your wrapper. Finally, it’s worth noting that support for dependency properties is provided by the System.Windows.DependencyObject type in WPF (and the Workflow.ComponentModel.DependencyObject type for Windows Workflow Foundation).

Changing states

The main benefit of the code above – the ScribbleCanvas implementation – is that it centralises all the state transition logic into a single method: StatePropertyChanged. This method is called every time the value of the StateProperty dependency property is modified; a consequence of registering it with the dependency property’s metadata. As you can see from the code, it calls RemoveHandlers() on the current state object and then calls AddHandlers() on the new.

Extending Scribble into Paint

So what happens if you need to pile on additional features? The great news is that with the State pattern in place the ScribbleCanvas class contains no event handling code for itself, allowing for much easier integration of new states (and thus new functionality). For example, consider what happens when you’re finally forced by your boss to add additional features to your Scribble application until it actually does transition into Paint. You can now see that each tool in the palette merely needs to toggle the Canvas into the appropriate matching state for the currently selected tool, a few of which are shown in Figure 5.

Figure 5
Figure 5: When Scribble becomes Paint

The toolbar implementation merely needs to associate each button with an appropriate CanvasState-derived object, which will in turn be used to set the State property on the Canvas when the user clicks the button: a prime candidate for the Command pattern.

Conclusion

The State pattern provides an excellent mechanism for clearing up code that can become littered with complex conditional statements. This is achieved by through composition: the current state for an object is provided by an external object to which the requests are delegated.

Like all patterns, though, there will be times when you want to tweak it somewhat. Rather than provide a simple delegation model, the implementation described above enables arbitrary state objects to respond to events raised by the canvas. There is a cost with this implementation: the CanvasState type maintains a reference to the ScribbleCanvas, thus introducing a bi-directional dependency that is not present in the standard State pattern.

The thing to bear in mind here, though, is that the CanvasState-derived types are likely to need to call type-specific methods on the canvas, and therefore it might not be worth trying to break that dependency in the first instance.

Additionally, each CanvasState type is currently responsible for changing the state of the canvas. Note that the design could easily be upgraded to support further interaction patterns, such as Mediator, to reduce these dependencies at a later point if necessary.

The key thing to remember, though, is that you mustn’t be frightened to change a pattern to suit the problem at hand. They are, after all, merely guidelines and not commandments.


David Wheeler is a freelance trainer and consultant, working primarily with Microsoft .NET. He’s a moderator on various Microsoft forums, and is a regular speaker at DevWeek and other conferences. He can be contacted at [email protected].

You might also like...

Comments

About the author

Dave Wheeler United Kingdom

Dave Wheeler is a freelance instructor and consultant who specialises in .NET application development. He’s a moderator on Microsoft’s ASP.NET and Silverlight forums and is a regular speaker at ...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone” - Bjarne Stroustrup