您的位置:首页 > 其它

步步为营 .NET 设计模式学习笔记 八、State(状态模式)

2011-04-12 00:55 811 查看
概述

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。

意图

状态模式主要解决的是当控制一个对象状态装换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简单化。

当一个对象行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。

<DesignPattern>State模式结构图





示例关系图

描述:一年有12个月,有四个季度,每个月都有一属于一个季度,根据月份得到这个季度的天气信息.可以用State模式来实现.

关系图:





代码设计:

先创建接口IQuarter.cs:

01
public
interface
IQuarter
02
{
03
///<summary>
04
///通过月份获取季度
05
///</summary>
06
///<paramname="Month"></param>
07
///<returns></returns>
08
QuarterGetQuarter();
09
10
///<summary>
11
///气候条件
12
///</summary>
13
///<returns></returns>
14
string
Climate();
15
}
再创建Quarter.cs:

01
public
abstract
class
Quarter:IQuarter
02
{
03
private
int
_Month=0;
04
public
int
Month
05
{
06
get
07
{
08
return
_Month;
09
}
10
set
11
{
12
_Month=value;
13
}
14
}
15
public
Quarter(
int
month)
16
{
17
this
.Month=month;
18
}
19
20
#regionIQuarter成员
21
22
public
abstract
QuarterGetQuarter();
23
24
public
abstract
string
Climate();
25
26
#endregion
27
28
29
}
1
再创建Spring.cs:
01
public
class
Spring:Quarter
02
{
03
04
private
Quarterquarter;
05
public
override
string
Climate()
06
{
07
return
"春风宜人,鸟语花香,正是旅游的好季节。"
;
08
}
09
10
public
override
QuarterGetQuarter()
11
{
12
if
(Month>3)
13
{
14
quarter=
new
Summer(Month);
15
return
quarter.GetQuarter();
16
}
17
return
new
Spring(Month);
18
}
19
public
Spring(
int
month):
base
(month)
20
{
21
22
}
23
}
再创建Summer.cs:

01
public
class
Summer:Quarter
02
{
03
private
Quarterquarter;
04
public
override
string
Climate()
05
{
06
return
"夏季天气炎热,酷暑难熬."
;
07
}
08
public
override
QuarterGetQuarter()
09
{
10
if
(Month<4)
11
{
12
quarter=
new
Spring(Month);
13
return
quarter.GetQuarter();
14
}
15
if
(Month>6)
16
{
17
quarter=
new
Autumn(Month);
18
return
quarter.GetQuarter();
19
}
20
21
return
new
Summer(
this
.Month);
22
23
}
24
public
Summer(
int
month):
base
(month)
25
{
26
27
}
28
}
再创建Autumn.cs:

01
public
class
Autumn:Quarter
02
{
03
private
Quarterquarter;
04
public
override
string
Climate()
05
{
06
return
"秋高气爽."
;
07
}
08
public
override
QuarterGetQuarter()
09
{
10
if
(Month<7)
11
{
12
quarter=
new
Summer(Month);
13
return
quarter.GetQuarter();
14
}
15
if
(Month>9)
16
{
17
quarter=
new
Winter(Month);
18
return
quarter.GetQuarter();
19
}
20
return
new
Autumn(Month);
21
22
}
23
public
Autumn(
int
month):
base
(month)
24
{
25
26
}
27
28
}
再创建Winter.cs:

01
public
class
Winter:Quarter
02
{
03
private
Quarterquarter;
04
public
override
string
Climate()
05
{
06
return
"冬天风寒,空气干燥."
;
07
}
08
public
override
QuarterGetQuarter()
09
{
10
11
if
(Month<10)
12
{
13
return
quarter.GetQuarter();
14
quarter=
new
Autumn(Month);
15
}
16
return
new
Winter(Month);
17
18
}
19
public
Winter(
int
month):
base
(month)
20
{
21
22
}
23
}
再创建MonthInfo.cs:

01
public
class
MonthInfo
02
{
03
private
Quarterquarter;
04
public
MonthInfo(
int
month)
05
{
06
//初始化为春季
07
quarter=
new
Spring(month);
08
quarter=quarter.GetQuarter();
09
}
10
public
string
ShowInfo()
11
{
12
if
(CheckMonthInfo())
13
{
14
return
GetQuarterClimate();
15
}
16
else
17
{
18
return
GetError();
19
}
20
}
21
private
string
GetQuarterClimate()
22
{
23
return
string
.Format(
"月份是:{0}月份,气候是:{1}"
,
this
.quarter.Month.ToString(),
this
.quarter.Climate());
24
}
25
private
string
GetError()
26
{
27
return
string
.Format(
"月份是:{0},是一个错误的信息."
,
this
.quarter.Month.ToString());
28
}
29
private
bool
CheckMonthInfo()
30
{
31
if
(
this
.quarter.Month>12||
this
.quarter.Month<1)
32
{
33
return
false
;
34
}
35
return
true
;
36
}
37
}
再调用它:

01
public
partial
class
Run:Form
02
{
03
public
Run()
04
{
05
InitializeComponent();
06
}
07
08
private
void
btnRun_Click(
object
sender,EventArgse)
09
{
10
for
(
int
i=0;i<15;i++)
11
{
12
MonthInfomonthInfo=
new
MonthInfo(i);
13
rtbResult.AppendText(monthInfo.ShowInfo()+
"\n"
);
14
}
15
}
16
}
结果如图:





1
何时采用

1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这

一相同的条件结构。tate模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不

依赖于其他对象而独立变化。

3.从代码角度来说,如果一个类有多种状态,并且在类内部通过的条件语句判断的类状态来实现不同行为时候可以把这些行为单独封装为状态类。

4.从应用角度来说,如果一个对象有多种状态,如果希望把对象状态的转化以及由不同状态产生的行为交给具体的状态类去做,那么可以考虑状态模式。

效果及实现要点

1.在环境角色中拥有状态角色的实例。

2.在状态角色中拥有环境角色的实例用于在具体状态中修改环境角色的状态。

3.状态对象之间的依赖可以通过加载外部配置的转化规则表等方法来消除。

4.状态模式和策略模式的主要区别是,前者的行为实现方式是由条件决定的,并且应当能不在客户端干预的情况下自己迁移到合适的状态,而后者的行为实现方式是由客户端选择的,并且能随时替换。

总结

1.优点:避免了为判断状态而产生的巨大的if或case语句。将对象行为交给状态类维护后,对于上层程序而言,仅需要维护状态之间的转换规则。
2.缺点:会导致某些系统有过多的具体状态类。

3.过多的状态对象可能会增加系统负担,可以考虑把各种状态角色实现为无状态对象的享元,需要保存的额外状态由环境角色进行统一管理和处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: