您的位置:首页 > 其它

状态模式(State)

2010-06-22 14:09 204 查看
因为前段日子比较忙,所以好些日子没有写博客了,而这个设计模式系列也就被耽搁了,

现在又比较清闲了,所以打算将这个系列写完,还望大家支持。

引子

先来看一个描述,这个描述呢是来自《Java 与模式》这本书:

说的是,在 1979 年出土的那个什么编钟,

所有的具体 State 代码
State0 类:
using System;
namespace StateElectronicOrgan
{
public class State0:ElectronicOrgan
{
public override void MakeMusic(Context context)
{
Console.WriteLine("MusicState:阰 0");
//发出 0 后便要发出 3 了,所以状态转换从状态 0 到状态 3
context.ElectronicOrgan = new State3();
}
}
}

State1 类:
using System;
namespace StateElectronicOrgan
{
public class State1 : ElectronicOrgan
{
public override void MakeMusic(Context context)
{
Console.WriteLine("MusicState: 1");
//发出 1 后便要发出 4 了,所以状态转换从状态 1 到状态 4
context.ElectronicOrgan = new State4();
}
}
}

State2 类:
using System;
namespace StateElectronicOrgan
{
public class State2 : ElectronicOrgan
{
public override void MakeMusic(Context context)
{
Console.WriteLine("MusicState: 2");
//发出 2 后便要发出 9 了,所以状态转换从状态 2 到状态 9
context.ElectronicOrgan = new State9();
}
}
}

State3 类:
using System;
namespace StateElectronicOrgan
{
public class State3 : ElectronicOrgan
{
public override void MakeMusic(Context context)
{
Console.WriteLine("MusicState: 3");
//发出 3 后便要发出 2 了,所以状态转换从状态 3 到状态 2
context.ElectronicOrgan = new State2();
}
}
}

State4 类:
using System;
namespace StateElectronicOrgan
{
public class State4 : ElectronicOrgan
{
public override void MakeMusic(Context context)
{
Console.WriteLine("MusicState: 4");
context.ElectronicOrgan = new State7();
}
}
}

State5 类:
using System;
namespace StateElectronicOrgan
{
public class State5 : ElectronicOrgan
{
public override void MakeMusic(Context context)
{
Console.WriteLine("MusicState: 5");
context.ElectronicOrgan = new State0();
}
}
}

State6 类:
using System;
namespace StateElectronicOrgan
{
public class State6 : ElectronicOrgan
{
public override void MakeMusic(Context context)
{
Console.WriteLine("MusicState: 6");
context.ElectronicOrgan = new State5();
}
}
}

State7 类:
using System;
namespace StateElectronicOrgan
{
public class State7 : ElectronicOrgan
{
public override void MakeMusic(Context context)
{
Console.WriteLine("Music Over . . . ");
}
}
}

State8 类:
using System;
namespace StateElectronicOrgan
{
public class State8 : ElectronicOrgan
{
public override void MakeMusic(Context context)
{
Console.WriteLine("MusicState: 8");
context.ElectronicOrgan = new State6();
}
}
}

State9 类:
using System;
namespace StateElectronicOrgan
{
public class State9 : ElectronicOrgan
{
public override void MakeMusic(Context context)
{
Console.WriteLine("MusicState: 9");
context.ElectronicOrgan = new State1();
}
}
}[/code]Context 类:

namespace StateElectronicOrgan
{
public class Context
{
private ElectronicOrgan electronicOrgan;

public ElectronicOrgan ElectronicOrgan
{
get { return electronicOrgan; }
set { electronicOrgan = value; }
}

//在构造函数中初始化第一个音符
public Context(ElectronicOrgan electronicOrgan)
{
this.electronicOrgan = electronicOrgan;
}

/// <summary>
/// 通过不断的请求来完成发出不同的声音,最后便成了一首曲子了
/// </summary>
public void Request()
{
electronicOrgan.MakeMusic(this);
}
}
}
客户端代码:

using System;
using StateElectronicOrgan;

namespace StateElectronicOrganTest
{
class Program
{
static void Main(string[] args)
{
Context context = new Context(new State8());
for (int i = 0; i < 10; i++)
{
context.Request();
}

Console.Read();
}
}
}
效果展示:





上面呢,就是通过状态模式来实现了电子琴的效果了,

相比于最初提出的两种方法(即直接在 Main 函数中,或者是在一个类中的方法中写入大量的 if 判断逻辑)来说,

使用状态模式的优点在于将和 Context 中的特定状态相关的行为局部化到各个具体的 State 类中,

然后就是解决了在一个方法中判断逻辑过多(单一职责原则)的问题,

并且将各个逻辑状态转移到了具体的 State 类中,从而减少了各个状态之间的依赖性。

不过状态模式的缺点也是显而易见的,就是奶奶的,平白加了这么多子类上去,

把人头都搞大了,问题似乎变得更加复杂了,我靠 . . .

所以,对于什么 2,3 个判断逻辑这些还是别用状态模式为妙。

其实呢,上面的这个电子琴的例子并适合用来介绍状态模式,因为,电子琴可以自己发出 n 中曲子,

而我上面使用状态模式呢,却钉死了每一个状态之间的切换,

所以上面的例子是在假设这个电子琴就只会播放一首曲子的前提下完成的。

总结状态模式的适用性

当一个对象的行为取决于它的状态时,并且必须在运行时根据状态来改变其行为时(差不多就是状态模式的定义了),

就可以使用状态模式。

当一个操作中有 n 多的判断逻辑时,并且这些分支是依赖于该对象的状态时,可以将每一个分支看做一个状态,

然后使用状态模式来进行处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: