这次来说说State状态模式,State状态模式用于我们在编程开发中大量用到 if Else的情况下,有很多分支的判断那么用状态模式就最好不过了,如在AI设计中的状态机就可以用State状态模式来设计一个AI机器人。 我们先来看看State状态模式的基本代码。
//抽象状态类 定义一个接口以封装与Context的一个特定状态相关的行为
abstract class State
{
public abstract void Handle(Context context);
}
class ConcreteStateA : State
{
public override void Handle(Context context)
{
context.State=new ConcreteStateB();
}
}
class ConcreteStateB : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateA();
}
}
class Context
{
private State state;
public Context(State state)
{
this.state = state;
}
public State State
{
get { return state; }
set
{
state = value;
Console.WriteLine("当前状态:"+state.GetType().Name);
}
}
public void Request()
{
state.Handle(this);
}
}
总的来说,这个设计模式其实很简单,一个发起人类,一个备忘录类,一个管理者类,发起人类就是我们客户端需要记录状态的类,备忘录类就保存我们需要记录的数据类,管理者类作为一个调用者。再看看运行代码:
Originator O = new Originator();
O.State = "On";
O.Show();
Caretaker c=new Caretaker();
c.Memento = O.CreateMemento();
O.State = "Off";
O.Show();
O.SetMemento(c.Memento); //恢复原初始状态
O.Show();
首先实现一个发起人 Originator类,然后设定状态为 On, 然后实现管理者类,然后在发起人中保存状态到管理者类,再改变状态为Off,输出为Off,然后恢复,在输出,状态又变回On了。是不是很简单,清晰呢,下面我们再来做个类似的游戏例子,模拟我们在游戏中的开发,读档存档功能。
class GamePlayer
{
private int hp;
private int mp;
private int atk;
public int Hp
{
get { return hp; }
set { hp = value; }
}
public int Mp
{
get { return mp; }
set { mp = value; }
}
public int Attack
{
get { return atk; }
set { atk = value; }
}
public void ShowState()
{
Console.WriteLine("生命值:" + Hp);
Console.WriteLine("魔法值:" + Mp);
Console.WriteLine("攻击力:" + Attack);
}
//设置初始值
public void Init()
{
Hp = 100;
Mp = 100;
Attack = 100;
}
public void InBattle()
{
Random rd=new Random();
Hp = rd.Next(0, 20);
Mp = rd.Next(0, 20);
Attack = rd.Next(0, 20);
}
//保存进度
public PlayerMemento SavePlayerState()
{
return (new PlayerMemento(Hp, Mp, Attack));
}
//恢复进度
public void RecoveryPlayerState(PlayerMemento memento)
{
this.Hp = memento.Hp;
this.Mp = memento.Mp;
this.Attack = memento.Attack;
}
}
//备忘录
class PlayerMemento
{
private int hp;
private int mp;
private int atk;
public int Hp
{
get { return hp; }
set { hp = value; }
}
public int Mp
{
get { return mp; }
set { mp = value; }
}
public int Attack
{
get { return atk; }
set { atk = value; }
}
public PlayerMemento(int hp, int mp, int atk)
{
this.hp = hp;
this.mp = mp;
this.atk = atk;
}
}
//管理者
class PlayerStateCaretaker
{
private PlayerMemento memento;
public PlayerMemento Menento
{
get { return memento; }
set { memento = value; }
}
}
首先还是做3个类,一个玩家类GamePlayer ,存放玩家需要保存的信息类,一个备忘录类PlayerMemento,存放数据,一个管理者类PlayerStateCaretaker,给外部调用。 然后就是运行的代码:
GamePlayer 赵日天=new GamePlayer();
赵日天.Init();
赵日天.ShowState();
Console.WriteLine("保存好进度,开始下副本");
//保存进度
PlayerStateCaretaker stateCaretaker=new PlayerStateCaretaker();
stateCaretaker.Menento = 赵日天.SavePlayerState();
//打怪消耗
赵日天.InBattle();
赵日天.ShowState();
Console.WriteLine("状态不行,还是回档吧");
//重新读档
赵日天.RecoveryPlayerState(stateCaretaker.Menento);
赵日天.ShowState();
首先声明玩家类和管理者类,然后玩家类初始化完成,保存信息后开始下副本,输出结果,各项数值消耗了,然后回档,管理者重新把备忘录的数据传回玩家类
再来总结下,备忘录模式应用分析
备忘录模式适用情形:
1、必须保存一个对象在某一个时刻的部分状态,这样以后需要时才能恢复到先前的状态。
2、如果用一个接口来让其他对象直接得到被保存对象的内部状态,将会暴露对象的实现细节并破坏对象的封装性。
备忘录模式特点:
1、保持封装边界。使用备忘录可以避免暴露一些只应由Originator管理却又必须存储在Originator之外的信息。该模式把可能很复杂的Originator内部信息对其他对象屏蔽起来,从而保持了封装边界。
2、简化Originator。在其他的保持封装性的设计中,Originator负责保持Client请求过的内部状态版本。把所存储管理的重任交给了Originator,让Client管理它们请求的状态将会简化Originator,并使得Client工作结束时无需通知Originator。