1.意图
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
2.结构与参与者
3.适用性
1)一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2)一个操作中含有庞大的多分支的条件语句,并且这些分支依赖于该对象的状态。这个状态通常用一个或者多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这个对象可以不依赖于其他对象而独立变化。
4.效果
1)它将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
2)它使得状态转换显示化。
3)State对象可被共享(见适用性2)。
5.代码示例
一个银行账户的例子。
#include <iostream>
#include <string>
using namespace std;
//抽象状态类
class State
{
public:
double m_amount; //这里写得非常丑陋
virtual WithDraw(double amount)=0;
virtual Diposit(double amount)=0;
};
//欠款状态
class RedState:public State
{
//private: StateChangeCheck()
public:
RedState(double amount){m_amount=amount;}
virtual WithDraw(double amount)
{
cout << "没有余额可以提现"<<endl;
}
virtual Diposit(double amount)
{
m_amount+=amount;
cout << "您存入了:¥"<<amount<<endl;
}
};
//白银VIP
class SilverState:public State
{
public:
SilverState(double amount){m_amount=amount;}
virtual WithDraw(double amount)
{
m_amount-=amount;
cout << "您取出了:¥"<<amount<<endl;
}
virtual Diposit(double amount)
{
m_amount+=amount;
cout << "您存入了:¥"<<amount<<endl;
}
};
//黄金VIP
class GoldState:public State
{
public:
GoldState(double amount){m_amount=amount;}
virtual WithDraw(double amount)
{
m_amount-=amount;
cout << "您取出了:¥"<<amount<<endl;
}
virtual Diposit(double amount)
{
m_amount+=amount;
cout << "您存入了:¥"<<amount<<endl;
}
};
//Context类
class Account
{
private:
State* m_pstate;
string m_sowner;
void StateChangeCheck()
//不改变状态都要新建另外一个实例
//每次存取款的操作都将引起一个实例的构建,并且可能是多余的
//怎么改进???
{
if (m_pstate->m_amount<0)
{
m_pstate=new RedState(m_pstate->m_amount);
cout << "小子,你欠款了,快还钱!!!"<<endl;
}
else if (m_pstate->m_amount>10000)
{
m_pstate=new GoldState(m_pstate->m_amount);
cout << "您现在的身份是黄金VIP"<<endl;
}
else
{
m_pstate=new SilverState(m_pstate->m_amount);
cout << "您现在的身份是白银VIP"<<endl;
}
}
public:
Account(string owner=""):m_sowner(owner)
{
m_pstate=new RedState(-10);
}
Account(State* state,string owner=""):m_sowner(owner),m_pstate(state){}
void WithDraw(double amount)
{
m_pstate->WithDraw(amount);
StateChangeCheck();
}
void Diposit(double amount)
{
m_pstate->Diposit(amount);
StateChangeCheck();
}
};
//客户端
int main()
{
SilverState* sp=new SilverState(1000);
Account* ap=new Account(sp,"sicofild");
ap->Diposit(10000.00);
ap->WithDraw(9000.00);
ap->WithDraw(5000);
ap->Diposit(100000.00);
return 0;
}