发布日期:2023-03-31来源:武汉北大青鸟武汉校区作者:武汉宏鹏
武汉北大青鸟java技术之设计模式系列技术讲解。
步:先能我参观了五处景点,先将五处景点定义一个枚举类型,代码如下:
/// <summary>
/// 故宫景点
/// </summary>
enum ImperialPalaceEnum
{
太和殿,
乾清宫,
御花园,
东六宫,
九龙壁
}
第二步:实现我每参观一处景点心里状态的变化,代码如下:
/// <summary>
/// 故宫参观类
/// </summary>
public class IPVisit
{
/// <summary>
/// 当前地点
/// </summary>
private ImperialPalaceEnum ipCurrentSpot;
public ImperialPalaceEnum IpCurrentSpot
{
set
{
ipCurrentSpot = value;
}
}
/// <summary>
/// 体会感受景点
/// </summary>
public void ExperienceSpot()
{
//体会感受当前景点
switch (ipCurrentSpot)
{
case ImperialPalaceEnum.太和殿:
Console.WriteLine("太和殿:皇上的家的客厅真的宏伟气派啊,脑海中幻想着当时举行大型仪式的情景甚是激动!");
break;
case ImperialPalaceEnum.乾清宫:
Console.WriteLine("乾清宫:是不是因为养心殿距离后宫很近雍正才搬过去的呀?");
break;
case ImperialPalaceEnum.御花园:
Console.WriteLine("御花园:御花园真的没有想象中的漂亮啊,很是失落.");
break;
case ImperialPalaceEnum.东六宫:
Console.WriteLine("东六宫:已经看不出当年嫔妃们生活的环境了,成展馆了.");
break;
case ImperialPalaceEnum.九龙壁:
Console.WriteLine("九龙壁:在宫中混,不会点三十六计都没脸见人.");
break;
}
}
第三步:主函数调用代码如下:
IPVisit visit = new IPVisit();
visit.IpCurrentSpot = ImperialPalaceEnum.太和殿;
visit.ExperienceSpot();
visit.IpCurrentSpot = ImperialPalaceEnum.乾清宫;
visit.ExperienceSpot();
visit.IpCurrentSpot = ImperialPalaceEnum.御花园;
visit.ExperienceSpot();
visit.IpCurrentSpot = ImperialPalaceEnum.东六宫;
visit.ExperienceSpot();
visit.IpCurrentSpot = ImperialPalaceEnum.九龙壁;
visit.ExperienceSpot();
运行结果为:
1 太和殿:皇上的家的客厅真的宏伟气派啊,脑海中幻想着当时举行大型仪式的情景甚是激动!
2 乾清宫:是不是因为养心殿距离后宫很近雍正才搬过去的呀?
3 御花园:御花园真的没有想象中的漂亮啊,很是失落.
4 东六宫:已经看不出当年嫔妃们生活的环境了,成展馆了.
5 九龙壁:在宫中混,不会点三十六计都没脸见人.
6 请按任意键继续. . .
二、状态模式
分析上边的代码我们会发现,参观故宫IPVisit的对象的行为取决于它的状态,例如:ipCurrentEnum属性等于不同的属性值时,体会景点方法:ExperienceSpot所做的行为就会不同。这样一来先就会导致我们一个方法出现了不同的职责,如果一个这个方法的责任过多那么维护起来必然是头疼的,例如看上边场景代码中的第二步中的代码,switch中的每一个case与break之间都实现了一种状态的行为。那么这个时候如果新增了一个景点(状态)就要修改此处的代码,导致违背了"开放-封闭原则"。这时有人就会说了,我们有的时候需求没有那么复杂我觉得用switch这样实现就很好,既简单又明了,这点我也非常赞同,设计就是根据实际需求来订的量身定做的设计才是更好的设计。话说的有点远了,那么如何优化我们上面的代码,使它可以灵活的扩展状态降低复杂度呢?不必担心,设计模式四人帮的前辈们已经在这类问题上给出了一个完美的解决方案,状态模式隆重登场!
1、什么是状态模式?
设计模式一书中的定义为:当一个对象在其内部状态改变时改变它的行为,对象看起来好像是修改其类。
2、状态模式类图
Context:维护一个状态的实例,这个实例定义的是当前的状态。
State: 该接口抽象Context一个特定状态的相关行为。
ConcreteState:实现了Context具体状态的行为。
3、状态模式代码实现
Context类用来维护一个当前状态的实例,表示当前状态,代码如下:
/// <summary>
/// 维护了当前状态的主体
/// </summary>
public class Context
{
public Context() { }
public Context(State state)
{
this.currentState = state;
}
private State currentState;
public State CurrentState
{
set
{
currentState = value;
}
}
/// <summary>
/// 执行当前状态
/// </summary>
public void Request()
{
currentState.Handle(this);
}
State接口:Context所需状态行为的抽象。代码如下:
public interface State
{
void Handle(Context context);
}
ConcreteState类:根据State的抽象实现了Context所需状态行为的实例,代码如下:
/// <summary>
/// 执行该状态对应的行为,设置下一个状态实例
/// </summary>
public class ConcereteStateA : State
{
public void Handle(Context context)
{
Console.WriteLine("状态A:处理行为执行了.....切换下一个状态B......");
context.CurrentState = new ConcereteStateB();
}
}
/// <summary>
/// 执行该状态对应的行为,设置下一个状态实例
/// </summary>
public class ConcereteStateB : State
{
public void Handle(Context context)
{
Console.WriteLine("状态B:处理行为执行了.....切换下一个状态A......");
context.CurrentState = new ConcereteStateA();
}
}
主函数调用如下:
Context context = new Context(new ConcereteStateA());
context.Request();
context.Request();
输出结果如下:
状态A:处理行为执行了.....切换下一个状态B......
状态B:处理行为执行了.....切换下一个状态A......
4、状态模式的优点
将特定状态的行为分开来,因为状态模式将所有状态的行为都放入到具体对象中,通过实现状态的抽象(接口State),可以很容易增加新的状态。
三、故宫游的状态模式实现
先呢,我在参观(Visit)的时候,会参观不同的景点,体会每个景点时我内心状态都会发生变化,也就是说我每参观一个景点都会有一个对应的状态。此时每个景点就应该对应一个具体的状态实现。所以我在参观不同景点的时候当前状态实例也需要跟着切换,类图如下:
先实现参观故宫类,每参观一个景点时都会改变我内心的状态,所以此时需要有一个属性代表当前状态,当体会该景点的时候就会执行对应的状态。代码如下:
/// <summary>
/// 参观故宫类
/// </summary>
public class IPVisitContext
{
public IPVisitContext() { }
public IPVisitContext(ISpotState state)
{
this.currentState = state;
}
/// <summary>
/// 当前状态
/// </summary>
private ISpotState currentState;
public ISpotState CurrentState
{
set
{
currentState = value;
}
}
/// <summary>
/// 参观景点 执行对应状态
/// </summary>
public void ExperienceSpot()
{
currentState.ExperienceSpot(this);
}
}
对于每个景点都会有不同的状态实例,此时需要一个状态的抽象,用户将来容易扩展新的状态实例,代码如下:
/// <summary>
/// 参观景点状态的抽象
/// </summary>
public interface ISpotState
{
void ExperienceSpot(IPVisitContext context);
}
接下来就是每个景点对应的状态实现了,代码如下:
/// <summary>
/// 太和殿状态行为实例
/// </summary>
public class 太和殿State : ISpotState
{
public void ExperienceSpot(IPVisitContext context)
{
Console.WriteLine("太和殿: 皇上的家的客厅真的宏伟气派啊,脑海中幻想着当时举行大型仪式的情景甚是激动!");
context.CurrentState = new 乾清宫State();
}
}
/// <summary>
/// 乾清宫状态行为实例
/// </summary>
public class 乾清宫State : ISpotState
{
public void ExperienceSpot(IPVisitContext context)
{
Console.WriteLine("乾清宫:是不是因为养心殿距离后宫很近雍正才搬过去的呀?");
context.CurrentState = new 御花园State();
}
}
/// <summary>
/// 御花园状态行为实例
/// </summary>
public class 御花园State : ISpotState
{
public void ExperienceSpot(IPVisitContext context)
{
Console.WriteLine("御花园:御花园真的没有想象中的漂亮啊,很是失落.");
context.CurrentState = new 东六宫State();
}
}
/// <summary>
/// 东六宫状态行为实例
/// </summary>
public class 东六宫State : ISpotState
{
public void ExperienceSpot(IPVisitContext context)
{
Console.WriteLine("东六宫:已经看不出当年嫔妃们生活的环境了,成展馆了.");
context.CurrentState = new 九龙壁State();
}
}
/// <summary>
/// 九龙壁状态行为实例
/// </summary>
public class 九龙壁State : ISpotState
{
public void ExperienceSpot(IPVisitContext context)
{
Console.WriteLine("九龙壁:在宫中混,不会点三十六计都没脸见人.");
}
}
主函数调用如下:
IPVisitContext context = new IPVisitContext(new 太和殿State());//从太和殿开始参观
context.ExperienceSpot();
context.ExperienceSpot();
context.ExperienceSpot();
context.ExperienceSpot();
context.ExperienceSpot();
运行结果如下:
1 太和殿:皇上的家的客厅真的宏伟气派啊,脑海中幻想着当时举行大型仪式的情景甚是激动!
2 乾清宫:是不是因为养心殿距离后宫很近雍正才搬过去的呀?
3 御花园:御花园真的没有想象中的漂亮啊,很是失落.
4 东六宫:已经看不出当年嫔妃们生活的环境了,成展馆了.
5 九龙壁:在宫中混,不会点三十六计都没脸见人.
6 请按任意键继续. . .
那么说了半天状态模式的好处了,那么怎么样来灵活的扩展状态呢?例如:我们现在需要加入一个景点的参观神武门也就是出宫的出口,我们只需如下几步即可:
步:新增一个神武门状态的类,代码如下:
/// <summary>
/// 神武门状态行为实例
/// </summary>
public class 神武门State : ISpotState
{
public void ExperienceSpot(IPVisitContext context)
{
Console.WriteLine("神武门:终于逛完故宫很是疲惫啊.");
}
}
第二步:将九龙壁的下一个状态挂接到神武门状态,代码如下:
/// <summary>
/// 九龙壁状态行为实例
/// </summary>
public class 九龙壁State : ISpotState
{
public void ExperienceSpot(IPVisitContext context)
{
Console.WriteLine("九龙壁:在宫中混,不会点三十六计都没脸见人.");
context.CurrentState = new 神武门State();
}
}
了解更多java技术请继续关注武汉北大青鸟官网。
Copyright (c) 2006-2023 武汉宏鹏教育咨询有限公司 版权所有 All Rights Reserved.