将当前工作场景所要做的工作内容(工作内容互相之间有顺序切换关系)交给具体状态类处理(每一种状态处理特定行为),避免所有繁琐的业务包杂在工作场景进行过多的分支切换操作,经过这样的分层之后,使得状态的切换也只是在状态类之间切换(通过传递工作场景对象指针或引用),虽说代码量增加了不少,但是对于业务的处理清晰了许多。
例一:
state.h
#ifndef STATE_H
#define STATE_H
#include <iostream>
using namespace std;
class Context;
//抽象状态类
class State
{
public:
//抽象状态的纯虚函数,子类需继承实现具体行为,依赖Context指针做为状态切换参数
virtual void Handle(Context* pContext) = 0;
};
//工作场景
class Context
{
public:
//定义_state的初始状态
Context(State* pState)
{
_state = pState;
}
~Context();
//对请求做处理,并设置下一状态
void Request()
{
if(NULL != _state)
{
_state->Handle(this);
}
}
void ChangeState(State* pState)
{
_state = pState;
}
private:
State* _state;
};
//具体状态类C
class ConcreteStateC : public State
{
public:
//执行该状态的行为并改变状态
virtual void Handle(Context* pContext);
};
//具体状态类B
class ConcreteStateB : public State
{
public:
//执行该状态的行为并改变状态为C状态
virtual void Handle(Context* pContext)
{
cout << "ConcreteStateB" << endl;
pContext->ChangeState(new ConcreteStateC());
}
};
//具体状态类A
class ConcreteStateA : public State
{
public:
//执行该状态的行为并改变状态为B状态
virtual void Handle(Context* pContext)
{
cout << "ConcreteStateA" << endl;
pContext->ChangeState(new ConcreteStateB());
}
};
#endif // STATE_H
state.cpp
#include "state.h"
//执行该状态的行为并改变状态为A状态
void ConcreteStateC::Handle(Context *pContext)
{
cout << "ConcreteStateC" << endl;
pContext->ChangeState(new ConcreteStateA());
}
main.cpp
int main()
{
State* pState = new ConcreteStateA();
Context* pContext = new Context(pState);
pContext->Request();
pContext->Request();
pContext->Request();
pContext->Request();
return 0;
}
例二:
car.h
#ifndef _CAR_H_
#define _CAR_H_
class Car;
class State
{
public:
virtual void forward(Car *) = 0;
virtual void turnLeft(Car *) = 0;
virtual void turnRight(Car *) = 0;
virtual void display() = 0;
};
class Car
{
public:
Car(){}
Car(int i,int j):x(i),y(j)
{
state = new North();
}
~Car()
{
delete state;
}
int getX(){ return x; }
int getY(){ return y; }
void forward();
void turnLeft();
void turnRight();
void disp();
class North : public State
{
void forward(Car *);
void turnLeft(Car *);
void turnRight(Car *);
void display();
};
class South : public State
{
void forward(Car *);
void turnLeft(Car *);
void turnRight(Car *);
void display();
};
class East : public State
{
void forward(Car *);
void turnLeft(Car *);
void turnRight(Car *);
void display();
};
class West : public State
{
void forward(Car *);
void turnLeft(Car *);
void turnRight(Car *);
void display();
};
private:
int x;
int y;
State *state;
};
#endif
car.cpp
#include <iostream>
#include "car.h"
using namespace std;
void Car::forward()
{
/*
switch(state)
{
case 0:
x++;break;
case 1:
x--;break;
case 2:
y--;break;
case 3:
y++;break;
default:
break;
}
*/
state->forward(this);
}
void Car::turnLeft()
{
//State *p = state;
state->turnLeft(this);
//delete p;
}
void Car::turnRight()
{
//State *p = state;
state->turnRight(this);
//delete p;
}
void Car::disp()
{
cout << "state: ";
state->display();
cout << getX() << " , " << getY() << endl;
}
//north
void Car::North::forward(Car *c)
{
c->y++;
}
void Car::North::turnLeft(Car *c)
{
c->state = new West();
}
void Car::North::turnRight(Car *c)
{
c->state = new East();
}
void Car::North::display()
{
cout << "North:";
}
//south
void Car::South::forward(Car *c)
{
c->y--;
}
void Car::South::turnLeft(Car *c)
{
c->state = new East();
}
void Car::South::turnRight(Car *c)
{
c->state = new West();
}
void Car::South::display()
{
cout << "South: ";
}
//east
void Car::East::forward(Car *c)
{
c->x++;
}
void Car::East::turnLeft(Car *c)
{
c->state = new North();
}
void Car::East::turnRight(Car *c)
{
c->state = new South();
}
void Car::East::display()
{
cout << "East:";
}
//west
void Car::West::forward(Car *c)
{
c->x--;
}
void Car::West::turnLeft(Car *c)
{
c->state = new South();
}
void Car::West::turnRight(Car *c)
{
c->state = new North();
}
void Car::West::display()
{
cout << "West: ";
}
main.cpp
#include <iostream>
#include "car.h"
using namespace std;
int main()
{
Car c(0,0); // 0,0
c.forward();//0,1
c.forward();//0,2
c.forward();//0.3
c.disp();
c.turnRight();
c.disp();
c.forward();//1,3
c.forward();//2,3
c.forward();//3,3
c.disp();
return 0;
}