State模式与Strategy模式

本文主要探讨状态模式与策略模式,指出二者易混淆,区别主要在环境的可变性上,若环境有明显状态转换应采用状态模式,否则选策略模式,还给出状态模式的抽象类、实现类及环境类的代码示例,展示其与策略模式在实现上的区别。
    在前面的随笔中我提到了用State模式来处理绩效包的分等,后来在 idior的回复中看到了关于使用State模式还是Strategy的取舍,随即温习了一下State模式(实际上是学习,用温习是假装看过)。所以将她俩之间的区别阐述如下:
    在我们设计的时候应该考虑 “不变性”“可变性”,如果说一个环境中状态可能一直有变化,比如在计算包的分等的时候可能不断切换分等算法,这样就应该使用State模式。而如果我们的需求是算法一旦确定不会改变,这也正是策略模式所处理的,因为策略模式环境一旦创建,那么在环境的整个生命周期内都不会改变具体策略类。
 
    在实现上,State模式在Context类中添加了State属性,也就是说在环境被创建后还可以切换各个State类,代码如下。
ExpandedBlockStart.gif ContractedBlock.gif /**/ /*******************************************************
InBlock.gif *                    状态模式
InBlock.gif *    状态模式与策略模式比较容易混淆,实际上她俩的区别主要
InBlock.gif * 在环境的可变性上,如果环境有明显的状态转换,那么就应该
InBlock.gif * 采用状态模式,否则选择策略模式。从这个例子中也可以看出
InBlock.gif * 她的实现和策略模式的实现的区别仅在状态类Context。
ExpandedBlockEnd.gif * ****************************************************
*/

None.gif
using  System;
None.gif
None.gif
namespace  StatePattern
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// Class1 的摘要说明。
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    class StatePattern
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 应用程序的主入口点。
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        [STAThread]
InBlock.gif        
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Context o_Context
=new Context(new RateClassifyCalculater());
InBlock.gif            o_Context.ContextIterface();
InBlock.gif
InBlock.gif            
//这里实现的状态的迁移,进而改变对象的行为。
InBlock.gif
            o_Context.State=new RangeClassifyCalculater();
InBlock.gif            o_Context.ContextIterface();
InBlock.gif            Console.ReadLine();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif    
状态模式的抽象类#region 状态模式的抽象类
InBlock.gif    
abstract public class  State
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 包分等计算的主逻辑框架
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public void MainCalculateLogic()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(
"Template Method Called");
InBlock.gif            ProjectCalculater();
InBlock.gif            PackageCalculater();
InBlock.gif            ClassifyPackage();
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 计算包中方案总得分的抽象方法
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        abstract public void ProjectCalculater();
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 计算最终包的得分的抽象方法
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        abstract public void PackageCalculater();
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 将计算好的包进行分等的抽象方法
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        abstract public void ClassifyPackage();
InBlock.gif
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif    
#endregion

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif    
状态模式的实现类#region 状态模式的实现类
InBlock.gif    
class RateClassifyCalculater:State
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 比例分等计算的方案计算具体实现
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public override void ProjectCalculater()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(
"Rate classify's calculater of project score called");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 比例分等计算的包分数计算具体实现
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public override void PackageCalculater()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(
"Rate classify's calculater of package score called");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 比例分等计算的包分等策略具体实现
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public override void ClassifyPackage()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(
"Rate classify's calculater of package classify logic called");
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
class RangeClassifyCalculater:State
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 分数区间分等计算的方案计算具体实现
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public override void ProjectCalculater()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(
"Range classify's calculater of project score called");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 分数区间分等计算的包分数计算具体实现
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public override void PackageCalculater()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(
"Range classify's calculater of package score called");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 分数区间分等计算的包分等策略具体实现
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public override void ClassifyPackage()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(
"Range classify's calculater of package classify logic called");
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif    
#endregion

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif    
状态模式的环境类,与策略模式的区别在与该类#region 状态模式的环境类,与策略模式的区别在与该类
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// 状态模式的环境类,用与控制状态间的转换
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public class Context
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private State state;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 环境的初始化
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <param name="initState">初始化状态</param>

InBlock.gif        public Context(State initState)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.state=initState;
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 环境类所维护的状态属性
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public State State
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return this.state;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.state=value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 环境接口
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public void ContextIterface()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(
"State Context Interface called");
InBlock.gif            
this.state.MainCalculateLogic();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif    
#endregion

ExpandedBlockEnd.gif}

None.gif

    执行结果如下:
State%20Pattern.jpg  

    另外环境类也可以作为参数传送给状态类,如果状态类需要就可以调节环境对象。这其实涉及到一个谁来改变状态的权衡,由环境来处理比较保险,由状态类自身决定状态的转换则更加灵活,但这种改变个人感觉好象有点失控,因为你可能在不知道的情况下环境类的状态就被改变了, 所以最好在 状态子类传入Context对象的时候显式的用ref关键字,这样就可以意识到可能Context对象要改变,如果不用ref关键字,虽然效果可能一样,但是起到的警示作用是不同的

    所以在使用State和Strategy模式的时候,首要考虑的是 环境状态是否是可变的

转载于:https://www.cnblogs.com/Masterpiece/archive/2004/12/28/82927.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值