|
|
||||||||
One thing expert designers know not to do is solve every problem from first principles.
—Gang of Four
About the Design Patterns
Coming up with a good structure for non-trivial state machines
isn’t easy. Experienced reactive-system designers know that
a reusable and flexible state machine design is difficult to get
right the first time. Yet, experienced designers repeatedly
conceive good state machines, while new designers are overwhelmed
by the options available and tend to fall back on convoluted
if... else... statements and multitude of flags they
have used before.
One thing that distinguishes an expert from a novice is that the expert can recognize the similarities among problems he has encountered in the past and reuse proven solutions that worked for him at the time. To share their expertise, OO designers started to catalog the proven solutions to recurring problems as OO design patterns [Gamma+ 95]. Similarly, state patterns started to appear [Douglass 99]. In contrast to the OO patterns, which are concerned with optimal ways of structuring classes and objects, the state patterns focus on effective ways of structuring states, events and transitions.
Just as an OO pattern, a state pattern has five essential elements:
- The pattern name—a word or two denoting the problem, solution and the consequences of a pattern. A good name is vital, because it will become part of your vocabulary.
- The problem—explanation of the problem the pattern addresses. A problem is often motivated by an example.
- The solution—description of the elements (states, transitions, events, actions, and extended state variables) comprising the solution, their relationships, responsibilities and collaborations.
- The sample code—presentation of a concrete implementation of an instance of the pattern. Usually the sample code implements the motivating example.
- The consequences—the results and trade-offs of applying the pattern.
Here you can find a mini-catalogue of basic state patterns (see Chapter 5 of PSiCC). The leading theme of all these patterns is reusing behavior through behavioral inheritance. This is in contrast to state patterns described in the book Doing Hard Time, by Bruce Powel Douglass [Douglass 99], which all revolve around orthogonal regions. The other distinguishing aspect of the state patterns presented here is that all are illustrated by concrete, executable code. A state diagram alone is not enough to understand a state pattern since “the devil is always in the detail”. To be practical, a pattern must be accompanied with a concrete working example that will help you truly comprehend and evaluate the pattern and give you a good starting point for your own instantiation of the pattern.
Top of page
Description of the Patterns
|
Provide common “look-and-feel”, but let clients specialize every aspect of a system’s behavior. |
|
Invent an event and post it to self. |
|
Control the sequence of events. |
|
Use state machines as components of other state machines. |
|
PATTERN: Transition to History Transition to the most recent state configuration of a given composite state. |
Top of page
Sample Code
The following code downloads are designed to "plug-into" the directory structure already established after the installation of the QP baseline code. In other words, you need to download and install the QP baseline code, before you install the design pattern code.
|
NOTES:
For simplicity, the sample code for the design patterns is provided as console applications (no GUIs). Patterns "Ultimate Hook" and "Transition to History" are implemented with just the QEP component, because they don't need timeout event generators or event queuing. Patterns "Orthogonal Component", "Reminder", and "Deferred Event" are implemented with QEP and QF, because they do need both timeout event generators and event queuing. The pattern "Deferred Event" is extended to show how to use the native QF event queue and QActive methods defer and recall() (added in QP 3.2.05) to very elegantly defer events. Also the deferred events are given reference numbers so that you can tell which particular requests are deferred and processed. |
| Patterns in QP/C | |||||
| QP™ Version |
Language | Operating System |
Compiler | Notes (date) |
Sample Code |
![]() QP/C 3.3.00 |
|
![]() ![]() DOS / Windows |
![]() Turbo C++ 1.01 (free download) |
Contains projects for TC++ 1.01 (Jan-25-07) |
![]() (177KB) |
| Patterns in QP/C++ | |||||
![]() QP/C++ 3.3.00 |
|
![]() ![]() DOS / Windows |
![]() Turbo C++ 1.01 (free download) |
Contains projects for TC++ 1.01 (Jan-25-07) |
![]() (254KB) |
![]() QP/C++ 3.3.00 |
|
![]() ![]() Linux / BSD |
![]() gcc |
Contains Makefiles (Jan-25-07) |
![]() (60KB) |
| Patterns in QP-nano | |||||
![]() QP-nano 1.5.03 |
|
![]() ![]() DOS / Windows |
![]() Turbo C++ 1.01 (free download) |
Contains projects for TC++ 1.01 (Dec-08-06) |
![]() (159KB) |
Top of page
Version: January 25, 2007













