内容摘录自《大话设计模式》
根据时间不同,呈现不同工作状态下的行为
工作状态-分类版
工作类
public class Work
{
private int hour;
public int Hour
{
get { return hour; }
set { hour = value; }
}
private bool finish = false;
public bool TaskFinished
{
get { return finish; }
set { finish = value; }
}
public void WriteProgram()
{
if (hour < 12)
{
Debug.Log(string.Format("当前时间:{0}点 上午工作,精神百倍", hour));
}
else if (hour < 13)
{
Debug.Log(string.Format("当前时间:{0}点 饿了,午饭:犯困,午休", hour));
}
else if (hour < 17)
{
Debug.Log(string.Format("当前时间:{0}点 下午状态还不错,继续努力", hour));
}
else
{
if (finish)
{
Debug.Log(string.Format("当前时间:{0}点 下班回家了", hour));
}
else
{
if (hour < 21)
{
Debug.Log(string.Format("当前时间:{0}点 加班哦,疲累之极", hour));
}
else
{
Debug.Log(string.Format("当前时间:{0}点 不行了,睡着了。", hour));
}
}
}
}
}
客户端程序
// 紧急项目
Work emergencyProjects = new Work();
emergencyProjects.Hour = 9;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 10;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 12;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 13;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 14;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 17;
emergencyProjects.WriteProgram();
emergencyProjects.TaskFinished = false;
emergencyProjects.Hour = 19;
emergencyProjects.WriteProgram();
emergencyProjects.Hour = 22;
emergencyProjects.WriteProgram();
结果表现
缺点:WriteProgram方法很长,而且有很多的判断分支,意味着它的责任过大了。
面向对象设计其实就是希望做到代码的责任分解。
状态模式
状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。
abstract class State
{
public abstract void Handle(Context context);
}
ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。
class ConcreteStateA : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateB(); // 设置A的下一状态是B
}
}
class ConcreteStateB : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateA(); // 设置B的下一状态是A
}
}
Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
class Context
{
private State state;
public State State
{
get { return state; }
set
{
state = value;
Debug.Log("当前状态:" + state.GetType().Name);
}
}
public Context(State _state) // 定义Context的初始状态
{
state = _state;
}
public void Request()
{
state.Handle(this); // 对请求做处理,并设置下一状态
}
}
客户端代码
Context c = new Context(new ConcreteStateA()); // 设置初始状态
// 不断的请求,同时更改状态
c.Request();
c.Request();
c.Request();
c.Request();
状态模式好处与用处
好处是将与特定状态相关的行为局部化,并且将不同的行为分割开来。
将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。消除了庞大的条件分支语句。
状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖,容易维护与扩展。
用处:
当一个对象的行为取决于它的状态,并且它必须运行时刻根据状态来改变它的行为时,就可以考虑用状态模式了。
工作状态-状态模式版
抽象状态类,定义一个抽象方法“写程序”
public abstract class State
{
public abstract void WriteProgram(Work w);
}
各种工作状态类
// 上午工作状态
public class ForenoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 12)
{
Debug.Log(string.Format("当前时间:{0}点 上午工作,精神百倍", w.Hour));
}
else
{
w.SetState(new NoonState()); // 超过12点,转入中午工作状态
w.WriteProgram();
}
}
}
// 中午工作状态
public class NoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 13)
{
Debug.Log(string.Format("当前时间:{0}点 饿了,午饭:犯困,午休。", w.Hour));
}
else
{
w.SetState(new AfterNoonState()); // 超过13点,转入下午工作状态
w.WriteProgram();
}
}
}
// 下午工作状态
public class AfterNoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 17)
{
Debug.Log(string.Format("当前时间:{0}点 下午状态还不错,继续努力", w.Hour));
}
else
{
w.SetState(new EveningState()); // 超过17点,转入晚上工作状态
w.WriteProgram();
}
}
}
// 晚上工作状态
public class EveningState : State
{
public override void WriteProgram(Work w)
{
if (w.TaskFinished)
{
w.SetState(new ResetState()); // 完成任务下班状态
w.WriteProgram();
}
else
{
if (w.Hour < 21)
{
Debug.Log(string.Format("当前时间:{0}点 加班哦,疲累之极", w.Hour));
}
else
{
w.SetState(new SleepingState()); // 超过21点,转入睡眠状态
w.WriteProgram();
}
}
}
}
// 睡眠状态
public class SleepingState : State
{
public override void WriteProgram(Work w)
{
Debug.Log(string.Format("当前时间:{0}点 不行了,睡着了", w.Hour));
}
}
// 下班休息状态
public class ResetState : State
{
public override void WriteProgram(Work w)
{
Debug.Log(string.Format("当前时间:{0}点 下班回家了", w.Hour));
}
}
工作类,此时没有了过长的分支判断语句
// 工作
public class Work
{
private State curState;
public Work()
{
curState = new ForenoonState(); // 工作初始化为上午工作状态
}
private double hour;
public double Hour // 钟点属性
{
get { return hour; }
set { hour = value; }
}
private bool finish = false;
public bool TaskFinished // 任务完成属性
{
get { return finish; }
set { finish = value; }
}
public void SetState(State s)
{
curState = s;
}
public void WriteProgram()
{
curState.WriteProgram(this);
}
}
客户端代码,没有任何改动。但我们的程序缺更加灵活易变了。