State pattern
Encyclopedia
The state pattern, which closely resembles Strategy Pattern
Strategy pattern
In computer programming, the strategy pattern is a particular software design pattern, whereby algorithms can be selected at runtime. Formally speaking, the strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable...

, is a behavioral
Behavioral pattern
In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns...

 software design pattern, also known as the objects for states pattern. This pattern is used in computer programming
Computer programming
Computer programming is the process of designing, writing, testing, debugging, and maintaining the source code of computer programs. This source code is written in one or more programming languages. The purpose of programming is to create a program that performs specific operations or exhibits a...

 to represent the state of an object
Object (computer science)
In computer science, an object is any entity that can be manipulated by the commands of a programming language, such as a value, variable, function, or data structure...

. This is a clean way for an object to partially change its type at runtime.

Structure

Pseudocode

Take, for example, a drawing program. The program has a mouse cursor, which at any point in time can act as one of several tools. Instead of switching between multiple cursor objects, the cursor maintains an internal state representing the tool currently in use. When a tool-dependent method is called (say, as a result of a mouse click), the method call is passed on to the cursor's state.

Each tool corresponds to a state. The shared abstract state class is AbstractTool:

class AbstractTool is
function moveTo(point) is
input: the location point the mouse moved to
(this function must be implemented by subclasses)

function mouseDown(point) is
input: the location point the mouse is at
(this function must be implemented by subclasses)

function mouseUp(point) is
input: the location point the mouse is at
(this function must be implemented by subclasses)

According to this definition, each tool must handle movement of the mouse cursor and also the start and end of any click or drag.

Using that base class, simple pen and selection tools could look like this:

subclass PenTool of AbstractTool is
last_mouse_position := invalid
mouse_button := up

function moveTo(point) is
input: the location point the mouse moved to
if mouse_button = down
(draw a line from the last_mouse_position to point)
last_mouse_position := point

function mouseDown(point) is
input: the location point the mouse is at
mouse_button := down
last_mouse_position := point

function mouseUp(point) is
input: the location point the mouse is at
mouse_button := up
subclass SelectionTool of AbstractTool is
selection_start := invalid
mouse_button := up

function moveTo(point) is
input: the location point the mouse moved to
if mouse_button = down
(select the rectangle between selection_start and point)

function mouseDown(point) is
input: the location point the mouse is at
mouse_button := down
selection_start := point

function mouseUp(point) is
input: the location point the mouse is at
mouse_button := up

For this example, the class for the context is called Cursor. The methods named in the abstract state class
(AbstractTool in this case) are also implemented in the context. In the context class, these methods invoke the corresponding method of the current state, represented by current_tool.

class Cursor is
current_tool := new PenTool

function moveTo(point) is
input: the location point the mouse moved to
current_tool.moveTo(point)

function mouseDown(point) is
input: the location point the mouse is at
current_tool.mouseDown(point)

function mouseUp(point) is
input: the location point the mouse is at
current_tool.mouseUp(point)

function usePenTool is
current_tool := new PenTool

function useSelectionTool is
current_tool := new SelectionTool

Notice how one Cursor object can act both as a PenTool and a SelectionTool at different points, by passing the appropriate method calls on to whichever tool is active. That is the essence of the state pattern. In this case, we could have combined state and object by creating PenCursor and SelectCursor classes, thus reducing the solution to simple inheritance, but in practice, Cursor may carry data which is expensive or inelegant to copy to a new object whenever a new tool is selected.

Java

The state interface and two implementations. The state's method has a reference to the context object and is able to change its state.

interface State {
void writeName(StateContext stateContext, String name);
}

class StateA implements State {
public void writeName(StateContext stateContext, String name) {
System.out.println(name.toLowerCase);
stateContext.setState(new StateB);
}
}

class StateB implements State {
private int count=0;
public void writeName(StateContext stateContext, String name){
System.out.println(name.toUpperCase);
// change state after StateB's writeName gets invoked twice
if(++count>1) {
stateContext.setState(new StateA);
}
}
}



The context class has a state variable which it instantiates in an initial state, in this case StateA. In its method, it uses the corresponding methods of the state object.

public class StateContext {
private State myState;
public StateContext {
setState(new StateA);
}

// normally only called by classes implementing the State interface
public void setState(State newState) {
this.myState = newState;
}

public void writeName(String name) {
this.myState.writeName(this, name);
}
}



And the usage:

public class TestClientState {
public static void main(String[] args) {
StateContext sc = new StateContext;
sc.writeName("Monday");
sc.writeName("Tuesday");
sc.writeName("Wednesday");
sc.writeName("Thursday");
sc.writeName("Saturday");
sc.writeName("Sunday");
}
}



According to the above code, the output of main from TestClientState should be:


monday
TUESDAY
WEDNESDAY
thursday
SATURDAY
SUNDAY
The source of this article is wikipedia, the free encyclopedia.  The text of this article is licensed under the GFDL.
 
x
OK