好处:将与特定状态相关的行为局部化,并且将不同状态的行为分隔开来。
使用场景:当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
这次我不用WPF的例子来讲,因为状态模式适合 工作流,一个任务完成,设置下一个任务。那我们就拿游戏来讲,主线任务。
这个游戏一共3个任务:
任务1:找到AY
任务2:跟踪AY,看看他都做了什么?
任务3:回到自己的房间
每个任务完成后才能进行下一个任务:
我们来编写任务类,任务调度类
任务类:GameTask, 任务是否已经结束IsEnd,任务是否接受IsAccept,接受任务方法AcceptTask和完成任务Done
public class GameTask { public GameTask() { } public GameTask(int taskId, string taskName) { this.TaskId = taskId; this.TaskName = taskName; } public string TaskName { get; set; } public int TaskId { get; set; } private bool isAccept = false; public bool IsAccept { get { return isAccept; } } private bool isEnd = false; public bool IsEnd { get { return isEnd; } set { isEnd = value; } } public virtual void AcceptTask() { this.isAccept = true; Console.WriteLine("任务:" + TaskName + " 已接受"); } public virtual void Done(GameContext context) { } }
任务调度:GameContext,设置当前任务,还有个完成任务。
====================www.ayjs.net 杨洋 wpfui.com ayui ay aaronyang=======请不要转载谢谢了。=========
public class GameContext { public GameContext(GameTask task) { this.Task = task; } private GameTask task; public GameTask Task { get { return task; } set { task = value; Console.WriteLine("当前主线任务:" + Task.TaskName); } } public void Done() { Task.Done(this); } }
接下来,我们只要添加任务即可
任务1 发现AY
public class TaskStep1 : GameTask { public TaskStep1() { } public TaskStep1(int taskId, string taskName) : base(taskId, taskName) { } public override void Done(GameContext context) { if (IsAccept) { this.IsEnd = true; Console.WriteLine(string.Format("任务{0}:{1} 已完成!恭喜", TaskId, TaskName)); context.Task = new TaskStep2(2, "跟踪AY,看看他都做了什么?"); } else { Console.WriteLine(string.Format("任务{0}:{1} 还未接受任务,请先接受.", TaskId, TaskName)); } } }
任务1完成后,设置任务2
public class TaskStep2 : GameTask { public TaskStep2() { } public TaskStep2(int taskId, string taskName) : base(taskId, taskName) { } public override void Done(GameContext context) { if (IsAccept) { this.IsEnd = true; Console.WriteLine(string.Format("任务{0}:{1} 已完成!恭喜!!", TaskId, TaskName)); Console.WriteLine(string.Format("恭喜你已经升到2级!")); Console.WriteLine("天啊,他这么晚睡觉,竟然还在写代码,回到房间,反思自己"); context.Task = new TaskStep3(3, "回到自己的房间"); } else { Console.WriteLine(string.Format("任务{0}:{1} 还未接受任务,请先接受.", TaskId, TaskName)); } } }
任务2完成后,设置任务3
public class TaskStep3 : GameTask { public TaskStep3() { } public TaskStep3(int taskId, string taskName) : base(taskId, taskName) { } public override void Done(GameContext context) { if (IsAccept) { this.IsEnd = true; Console.WriteLine(string.Format("任务{0}:{1} 已完成!恭喜", TaskId, TaskName)); Console.WriteLine(string.Format("你已经完成了今天所有的任务!")); } else { Console.WriteLine(string.Format("任务{0}:{1} 还未接受任务,请先接受.", TaskId, TaskName)); } } }
好了,如果还有其他任务,以此类推,设置一个流程
客户端代码如下: 当天任务开始时候,如果没有接受任务,问他接受,接受后就完成,然后进行下一个任务提示,但是代码只要写1个gametask.Done即可
状态模式就是定义了1个流程。
TaskStep1 t1 = new TaskStep1(1, "找到AY"); GameContext gametask = new GameContext(t1); do { gametask.Done(); if (!gametask.Task.IsAccept) { do{ Console.WriteLine("是否接受任务:"+gametask.Task.TaskName+"? 输入:Y/N"); string isaccept = Console.ReadLine(); if (isaccept == "Y") { gametask.Task.AcceptTask(); } } while (!gametask.Task.IsAccept); } } while (!gametask.Task.IsEnd); Console.WriteLine("\n========本demo由www.ayjs.net的杨洋,ay编写=="); Console.ReadKey();
效果预览:
写到了这里,大家应该知道状态模式的具体应用了吧,感觉还是比较强大的一个模式。他的写法,与前面我们学的 策略模式很像。但是两个模式却实质解决场景不一致。
AY的讲解:策略模式侧重于算法,你是什么需求,我返回某个策略去处理你的业务。而不像状态模式给你一套流程。