状态模式简介
当一个对象内在状态改变时允许其改变行为,这个对象看起来像时改变了其类。状态模式可实现:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
状态模式解决了代码中包含大量与对象状态有关的条件语句。
优点: | 缺点: |
---|---|
1. 封装了转换规则 | 1. 状态模式的使用必然会增加系统类和对象的个数 |
2. 枚举可能的状态,在枚举状态之前需要确定状态种类 | 2. 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱 |
3. 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为 | 3. 状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码 |
4. 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块 | / |
5. 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。 | / |
C# 状态模式Demo模板
using System;
namespace StatePattern
{
class Program
{
static void Main(string[] args)
{
Context context = new Context();
context.State = new ConcreteState1();
context.Request();
context.Request();
context.Request();
context.Request();
context.Request();
context.Request();
context.Request();
context.Request();
context.Request();
}
}
public abstract class AbstractState
{
public abstract void Handler(Context context);
}
public class ConcreteState1 : AbstractState
{
public override void Handler(Context context)
{
context.State = new ConcreteState2();
}
}
public class ConcreteState2 : AbstractState
{
public override void Handler(Context context)
{
context.State = new ConcreteState3();
}
}
public class ConcreteState3 : AbstractState
{
public override void Handler(Context context)
{
context.State = new ConcreteState1();
}
}
public class Context
{
private AbstractState state;
public AbstractState State
{
get { return state; }
set { state = value; Console.WriteLine("当前状态:{0}", State.GetType().Name ); }
}
public void Request()
{
this.State.Handler(this);
}
}
}
测试结果:
C# 实现qq邮箱日历问候语
using System;
namespace StatePattern
{
/// <summary>
/// 状态模式 实现qq邮箱 时间问候语显示
/// </summary>
class Program
{
static void Main(string[] args)
{
Context context = new Context(20); // 设置时间 Hour=20;
context.State = new MorningState();
context.Request();
Console.WriteLine("----------------------");
context.Hour = 15;
context.Request();
Console.WriteLine("----------------------");
context.Hour = 10;
context.Request();
Console.WriteLine("----------------------");
}
}
public abstract class AbstractState
{
public abstract void Handler(Context context);
}
public class MorningState : AbstractState
{
public override void Handler(Context context)
{
if( context.Hour%24 > 9 && context.Hour%24 <= 12)
{
Console.WriteLine("早上好");
}
else
{
context.State = new AfternoonState();
context.Request();
}
}
}
public class AfternoonState : AbstractState
{
public override void Handler(Context context)
{
if (context.Hour % 24 > 12 && context.Hour % 24 <= 18)
{
Console.WriteLine("下午好");
}
else
{
context.State = new EveningState();
context.Request();
}
}
}
public class EveningState : AbstractState
{
public override void Handler(Context context)
{
if (context.Hour % 24 > 18 && context.Hour % 24 < 24)
{
Console.WriteLine("晚上好");
}
else
{
context.State = new MorningState();
context.Request();
}
}
}
public class Context
{
private int hour;
public int Hour
{
get; set;
}
public Context(int nowHour)
{
this.Hour = nowHour;
}
private AbstractState state;
public AbstractState State
{
get { return state; }
set { state = value; Console.WriteLine("当前状态:{0}", State.GetType().Name ); }
}
public void Request()
{
this.State.Handler(this);
}
}
}
通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法。而且,状态模式的实现类的方法,一般返回值,或者是改变实例变量的值。也就是说,状态模式一般和对象的状态有关。实现类的方法有不同的功能,覆盖接口中的方法。状态模式和命令模式一样,也可以用于消除 if…else 等条件选择语句。
参考资料
https://m.runoob.com/design-pattern/state-pattern.html
https://www.bilibili.com/video/av78515440?p=16