13.1状态模式定义:
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
13.2状态模式UML类图:
13.3应用场景:
1、当一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
2、一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常, 有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
13.4状态模式分析与实现(c#描述):
public interface IState
{
//动作 状态
//买票:等待进场验票
//进场:等待电影开始
//看电影:等待电影结束
//出场:等待下一场电影
//引起状态变化的4个动作,这4个动作均是同一Context发出。
void BuyTicket();
void Enter();
void See();
void Exit();
}
//Context对象,不同的行为切换不同的状态。
public class Person
{
//将状态对象组合进来
private IState _waitingForCheckin;
private IState _waitingForMovieStart;
private IState _waitingForMovieEnd;
private IState _waitingForNextMovie;
public IState WaitingForCheckin
{
get { return _waitingForCheckin; }
set { _waitingForCheckin = value; }
}
public IState WaitingForMovieStart
{
get { return _waitingForMovieStart; }
set { _waitingForMovieStart = value; }
}
public IState WaitingForMovieEnd
{
get { return _waitingForMovieEnd; }
set { _waitingForMovieEnd = value; }
}
public IState WaitingForNextMovie
{
get { return _waitingForNextMovie; }
set { _waitingForNextMovie = value; }
}
private IState CurrentState;//当前状态
public Person()
{
//为每个状态初始化一个状态对象,并把当前Context对象传给每一个状态对象。
this._waitingForCheckin = new WaitingForCheckin(this);
this._waitingForMovieStart = new WaitingForMovieStart(this);
this._waitingForMovieEnd = new WaitingForMovieEnd(this);
this._waitingForNextMovie = new WaitingForNextMovie(this);
this.CurrentState = this._waitingForNextMovie;//设置一开始的当前状态为等待下一场电影状态。
}
public void BuyTicket()//买票
{
this.CurrentState.BuyTicket();
}
public void Enter()//进场
{
this.CurrentState.Enter();
}
public void See()//看电影
{
this.CurrentState.See();
}
public void Exit()//出场
{
this.CurrentState.Exit();
}
public void SetState(IState aobj_State)//设置当前状态
{
this.CurrentState = aobj_State;
}
}
public class WaitingForCheckin:IState
{
private Person iobj_Person;
public WaitingForCheckin(Person aobj_Person)
{
this.iobj_Person = aobj_Person;
}
public void BuyTicket()
{
Console.WriteLine("这个操作不允许:已经买过票了。");
}
public void Enter()
{
Console.WriteLine("进场吧,呵呵。");
this.iobj_Person.SetState(this.iobj_Person.WaitingForMovieStart);//状态转换
}
public void See()
{
Console.WriteLine("这个操作不允许:还没进场呢。");
}
public void Exit()
{
Console.WriteLine("这个操作不允许:电影都没看呢。");
}
}
public class WaitingForMovieStart : IState
{
private Person iobj_Person;
public WaitingForMovieStart(Person aobj_Person)
{
this.iobj_Person = aobj_Person;
}
public void BuyTicket()
{
Console.WriteLine("这个操作不允许:已经买过票了。");
}
public void Enter()
{
Console.WriteLine("这个操作不允许:已经进场了。");
}
public void See()
{
Console.WriteLine("开始看电影吧。");
this.iobj_Person.SetState(this.iobj_Person.WaitingForMovieEnd);//状态转换
}
public void Exit()
{
Console.WriteLine("这个操作不允许:电影还没看完呢。");
}
}
public class WaitingForMovieEnd : IState
{
private Person iobj_Person;
public WaitingForMovieEnd(Person aobj_Person)
{
this.iobj_Person = aobj_Person;
}
public void BuyTicket()
{
Console.WriteLine("这个操作不允许:已经买过票了。");
}
public void Enter()
{
Console.WriteLine("这个操作不允许:已经进场了。");
}
public void See()
{
Console.WriteLine("这个操作不允许:已经看完电影了。");
}
public void Exit()
{
Console.WriteLine("出场吧,呵呵。");
this.iobj_Person.SetState(this.iobj_Person.WaitingForNextMovie);//状态转换
}
}
public class WaitingForNextMovie : IState
{
private Person iobj_Person;
public WaitingForNextMovie(Person aobj_Person)
{
this.iobj_Person = aobj_Person;
}
public void BuyTicket()
{
Console.WriteLine("现在可以买票了。");
this.iobj_Person.SetState(this.iobj_Person.WaitingForCheckin);//状态转换
}
public void Enter()
{
Console.WriteLine("这个操作不允许:还没买票呢。");
}
public void See()
{
Console.WriteLine("这个操作不允许:还没进场呢。");
}
public void Exit()
{
Console.WriteLine("这个操作不允许:已经出场了。");
}
}
//调用类
public class State_Test
{
public static void Do()
{
//测试1,输出:现在可以买票了。 进场吧,呵呵。 开始看电影吧。 出场吧,呵呵。
Person lobj_Person = new Person();
lobj_Person.BuyTicket();
lobj_Person.Enter();
lobj_Person.See();
lobj_Person.Exit();
//测试2,输出:这个操作不允许:还没买票呢。 现在可以买票了。 这个操作不允许:电影都没看呢。这个操作不允许:还没进场呢。
lobj_Person.Enter();
lobj_Person.BuyTicket();
lobj_Person.Exit();
lobj_Person.See();
}
}
状态模式和策略模式的区别:
状态模式和策略模式的类图是一样的,但这两个模式的差别在于他们的意图。一般来说,我们把策略模式想成是一种除了继承之外的弹性替代方案。如果使用继承定义一个类的行为,你将被这个行为困住,甚至要修改他都很难。有了策略模式,就可以组合不同的对象来改变行为。而状态模式是不用在Context中放置许多条件判断的替代方案。通过将行为包装进状态对象中,你可以通过Context中简单地改变状态对象来改变Context的行为。