设计模式解析和实现(C++, java)之二十--状态(state)模式

来源:互联网 发布:淘宝退货上传照片要求 编辑:程序博客网 时间:2024/05/17 01:44

1定义:

 如果一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态改变和行为动作分开。每一个状态对应一个class。

2作用:

State模式主要解决了在开发时需要根据不同的状态进行不同的处理操作的问题。state模式采用了对这些不同的状态进行封装的方式处理这类问题,弹头状态改变的时候进行处理然后切换到另一种状态。也即是状态的改变交给了具体的状态类去负责。同时state模式和strategy模式哟很多相似的地方,需要说明的是两者思想都一致。

 

3UML结构图:

状态模式(State)结构图

 

4使用:

4.1 定义一个state接口,接口使用统一的方法,用以封装一个特定状态所对应的行为。

4.2 定于具体不同状态类并实现其接口。

4.3 每一个状态类都实现context一个状态所对应的行为。

4.4顶一个状态管理器context。

 

Java的实现如下:

state类,抽象状态基类,并定一个接口封装与context交互的一个特定的行为。

interface State{
public void handle(Context ctx);
}
class ConcreteStateA implements State{
  
public void handle(Context ctx) {
 System.out.println("handle by ConcreteStateA");
 if(ctx!=null){
 ctx.ChangeState(new ConcreteStateB());
 }
 
}
}
class ConcreteStateB implements State{
  
public void handle(Context ctx) {
 System.out.println("handle by ConcreteStateB");
 if(ctx!=null){
 ctx.ChangeState(new ConcreteStateA());
 }
 
}
}
class Context{
private State _state;
public Context(State state){
 _state=state;
}
public void request(){
 if(_state!=null){
 _state.handle(this);
 }
}
public void ChangeState(State s){
 if(_state!=null){
 _state=null;
 }
 _state=s;
}
}
public class StateClient {
  
public static void main(String[] args) {
 State state=new ConcreteStateA();
 Context context=new Context(state);
 context.request();
 context.request();
 context.request();
 context.request();
  
}
  
}

C++代码实现:

1)State.h

/********************************************************************

#ifndef STATE_H
#define STATE_H

class State;

class Context
{
public:
    Context(State
* pState);
    
~Context();
    
void Request();
    
void ChangeState(State *pState);

private:
    State 
*m_pState;
}
;

class State
{
public:
    
virtual ~State(){}

    
virtual void Handle(Context* pContext) = 0;
}
;

class ConcreateStateA
    : 
public State
{
public:
    
void Handle(Context* pContext);
}
;

class ConcreateStateB
    : 
public State
{
public:
    
void Handle(Context* pContext);
}
;

#endif


2)State.cpp

/********************************************************************


#include 
"State.h"
#include 
<iostream>

Context::Context(State
* pState)
    : m_pState(pState)
{

}


Context::
~Context()
{
    delete m_pState;
    m_pState 
= NULL;
}


void Context::Request()
{
    
if (NULL != m_pState)
    
{
        m_pState
->Handle(this);
    }

}


void Context::ChangeState(State *pState)
{
    
if (NULL != m_pState)
    
{
        delete m_pState;
        m_pState 
= NULL;
    }

    
    m_pState 
= pState;
}


void ConcreateStateA::Handle(Context* pContext)
{
    std::cout 
<< "Handle by ConcreateStateA/n";
    
    
if (NULL != pContext)
    
{
        pContext
->ChangeState(new ConcreateStateB());
    }

}


void ConcreateStateB::Handle(Context* pContext)
{
    std::cout 
<< "Handle by ConcreateStateB/n";

    
if (NULL != pContext)
    
{
        pContext
->ChangeState(new ConcreateStateA());
    }

}


3)Main.cpp
/********************************************************************

#include 
"State.h"

int main()
{
    State 
*pState = new ConcreateStateA();
    Context 
*pContext = new Context(pState);
    pContext
->Request();
    pContext
->Request();
    pContext
->Request();

    delete pContext;

    
return 0;
}

  六、适用性

  1)一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。

  2)一个对象含有庞大的条件分支语句,这些分支依赖于它的状态。这个状态通常用一个或多个枚举常量表示。通常有多个操作包含这一相同的结构。State模式将每一个分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

  七、优缺点

  1)优点: 避免了为判断状态而产生的巨大的if或case语句。 将对象行为交给状态类维护后,对于上层程序而言,仅需要维护状态之间的转换规则。

  2)会导致某些系统有过多的具体状态类。