[size=large]1、意图
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
2、别名
状态对象(Objects for States)
3、动机
考虑一个表示网络连接的类TCPConnection。一个TCPConnection对象的状态处于若干不同状态之一:连接已建立(Established)、正在监听(Listening)、连接已关闭(Closed)。当一个TCPConnection对象收到其他对象的请求时,它根据自身的当前状态作出不同的反应。例如,一个Open请求的结果依赖于该连接是处于连接已关闭状态还是连接已建立状态。State模式描述了TCPConnection如何在每一种状态下表现出不同的行为。
这一模式的关键思想是引入一个称为TCPState的抽象类来表示网络的连接状态。TCPState类为各表示不同的操作状态的子类声明了一个公共接口。TCPState的子类实现与特定状态相关的行为。例如,TCPEstablished和TCPClosed类分别实现了特定于TCPConnection的连接已建立状态和连接已关闭状态的行为。
[img]http://dl2.iteye.com/upload/attachment/0085/7569/1d8ec3f0-0a07-32d3-beda-53a17d6c26e5.jpg[/img]
TCPConnection类维护一个表示TCP连接当前状态的状态对象(一个TCPState子类的实例)。TCPConnection类将所有与状态相关的请求委托给这个状态对象。TCPConnection使用它的TCPState子类实例来执行特定于连接状态的操作。
一旦连接状态改变,TCPConnection对象就会改变它所使用的状态对象。例如当连接从已建立状态转为已关闭状态时,TCPConnection会用一个TCPClosed的实例来代替原来的TCPEstablished的实例。
4、适用性
在下面的两种情况下均可使用State模式:
一个对象的行为取决去它的状态,并且它必须在运行时刻根据状态改变它的行为。
一个操作中含有庞大的多分支的条件语句,并且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放到一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
5、结构
[img]http://dl2.iteye.com/upload/attachment/0085/7612/4d973772-329a-3577-8e6e-300678c1fb84.jpg[/img]
6、参与者
Context(环境,如TCPConnection)
——定义客户感兴趣的接口。
——维护一个ConcreteState子类的实例,这个实例定义当前状态。
State(状态,如TCPState)
——定义一个接口以封装与Context的一个特定状态相关的行为。
ConcreteState subclasses(具体状体子类,如TCPEstablished,TCPListen,TCPClosed)
——每一个子类实现一个与Context的一个状态相关的行为[/size]
7、代码示例
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
2、别名
状态对象(Objects for States)
3、动机
考虑一个表示网络连接的类TCPConnection。一个TCPConnection对象的状态处于若干不同状态之一:连接已建立(Established)、正在监听(Listening)、连接已关闭(Closed)。当一个TCPConnection对象收到其他对象的请求时,它根据自身的当前状态作出不同的反应。例如,一个Open请求的结果依赖于该连接是处于连接已关闭状态还是连接已建立状态。State模式描述了TCPConnection如何在每一种状态下表现出不同的行为。
这一模式的关键思想是引入一个称为TCPState的抽象类来表示网络的连接状态。TCPState类为各表示不同的操作状态的子类声明了一个公共接口。TCPState的子类实现与特定状态相关的行为。例如,TCPEstablished和TCPClosed类分别实现了特定于TCPConnection的连接已建立状态和连接已关闭状态的行为。
[img]http://dl2.iteye.com/upload/attachment/0085/7569/1d8ec3f0-0a07-32d3-beda-53a17d6c26e5.jpg[/img]
TCPConnection类维护一个表示TCP连接当前状态的状态对象(一个TCPState子类的实例)。TCPConnection类将所有与状态相关的请求委托给这个状态对象。TCPConnection使用它的TCPState子类实例来执行特定于连接状态的操作。
一旦连接状态改变,TCPConnection对象就会改变它所使用的状态对象。例如当连接从已建立状态转为已关闭状态时,TCPConnection会用一个TCPClosed的实例来代替原来的TCPEstablished的实例。
4、适用性
在下面的两种情况下均可使用State模式:
一个对象的行为取决去它的状态,并且它必须在运行时刻根据状态改变它的行为。
一个操作中含有庞大的多分支的条件语句,并且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放到一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
5、结构
[img]http://dl2.iteye.com/upload/attachment/0085/7612/4d973772-329a-3577-8e6e-300678c1fb84.jpg[/img]
6、参与者
Context(环境,如TCPConnection)
——定义客户感兴趣的接口。
——维护一个ConcreteState子类的实例,这个实例定义当前状态。
State(状态,如TCPState)
——定义一个接口以封装与Context的一个特定状态相关的行为。
ConcreteState subclasses(具体状体子类,如TCPEstablished,TCPListen,TCPClosed)
——每一个子类实现一个与Context的一个状态相关的行为[/size]
7、代码示例
interface Statelike {
/**
* Writer method for the state name.
* @param STATE_CONTEXT
* @param NAME
*/
void writeName(final StateContext STATE_CONTEXT, final String NAME);
}
class StateA implements Statelike {
/* (non-Javadoc)
* @see state.Statelike#writeName(state.StateContext, java.lang.String)
*/
@Override
public void writeName(final StateContext STATE_CONTEXT, final String NAME) {
System.out.println(NAME.toLowerCase());
STATE_CONTEXT.setState(new StateB());
}
}
class StateB implements Statelike {
/** State counter */
private int count = 0;
/* (non-Javadoc)
* @see state.Statelike#writeName(state.StateContext, java.lang.String)
*/
@Override
public void writeName(final StateContext STATE_CONTEXT, final String NAME) {
System.out.println(NAME.toUpperCase());
// Change state after StateB's writeName() gets invoked twice
if(++count > 1) {
STATE_CONTEXT.setState(new StateA());
}
}
}
The context class has a state variable that 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 Statelike myState;
/**
* Standard constructor
*/
public StateContext() {
setState(new StateA());
}
/**
* Setter method for the state.
* Normally only called by classes implementing the State interface.
* @param NEW_STATE
*/
public void setState(final Statelike NEW_STATE) {
myState = NEW_STATE;
}
/**
* Writer method
* @param NAME
*/
public void writeName(final String NAME) {
myState.writeName(this, NAME);
}
}
public class TestClientState {
public static void main(String[] args) {
final StateContext SC = new StateContext();
SC.writeName("Monday");
SC.writeName("Tuesday");
SC.writeName("Wednesday");
SC.writeName("Thursday");
SC.writeName("Friday");
SC.writeName("Saturday");
SC.writeName("Sunday");
}
}
monday
TUESDAY
WEDNESDAY
thursday
FRIDAY
SATURDAY
sunday