何时使用?
State模式在实际使用中比较多适合"状态切换".我们经常会使用If 进行状态切换如果针对状态这样判断切换反复出现我们就要联想到是否可以采取State模式了
不只是根据状态也有根据属性.如果某个对象属性区别对象行为就不样这点在数据库系统中出现频率比较高我们经常会在个数据表尾部加上property属性含义字段用以标识记录中些特殊性质记录这种属性改变(切换)又是随时可能发生就有可能要使用State
是否使用?
在实际使用类似开关样状态切换是很多但有时并不是那么明显取决于你经验和对系统理解深度
这里要阐述是"开关切换状态" 和" 般状态判断"是有些区别 " 般状态判断"也是有 ..结构例如:
(which1) state="hello";
(which2) state="hi";
(which3) state="bye";
这是个 " 般状态判断"state值区别是根据which变量来决定which和state没有关系.如果改成:
(state.euqals("bye")) state="hello";
(state.euqals("hello")) state="hi";
(state.euqals("hi")) state="bye";
这就是 "开关切换状态"是将state状态从"hello"切换到"hi"再切换到""bye";在切换到"hello"好象个旋转开关这种状态改变就可以使用State模式了
如果单纯有上面种将"hello"-->"hi"-->"bye"-->"hello"这个方向切换也不定需要使用State模式State模式会建立很多子类复杂化但是如果又发生另外个行为:将上面切换方向反过来切换或者需要任意切换就需要State了
请看下例:
public Context{
private Color state=null;
public void push(){
//如果当前red状态 就切换到blue
(stateColor.red) state=Color.blue;
//如果当前blue状态 就切换到green
(stateColor.blue) state=Color.green;
//如果当前black状态 就切换到red
(stateColor.black) state=Color.red;
//如果当前green状态 就切换到black
(stateColor.green) state=Color.black;
Sample sample= Sample(state);
sample.operate();
}
public void pull(){
//和push状态切换正好相反
(stateColor.green) state=Color.blue;
(stateColor.black) state=Color.green;
(stateColor.blue) state=Color.red;
(stateColor.red) state=Color.black;
Sample2 sample2= Sample2(state);
sample2.operate();
}
}
在上例中我们有两个动作push推和pull拉这两个开关动作改变了Context颜色至此我们就需要使用State模式优化它另外注意:但就上例state变化只是简单颜色赋值这个具体行为是很简单State适合巨大具体行为因此在就本例实际使用中也不定非要使用State模式这会增加子类数目简单变复杂
例如: 银行帐户 经常会在Open 状态和Close状态间转换
例如: 经典TcpConnection Tcp状态有创建 侦听 关闭 3个并且反复转换其创建 侦听 关闭具体行为不是简单两句就能完成适合使用State
例如:信箱POP帐号 会有 4种状态 start HaveUsername Authorized quit每个状态对应行为应该是比较大.适合使用State
例如:在工具箱挑选区别工具可以看成在区别工具中切换适合使用State.如 具体绘图用户可以选择区别工具绘制方框 直线 曲线这种状态切换可以使用State
如何使用
State需要两种类型实体参和:
1.state manager 状态管理器就是开关如上面例子Context实际就是个state manager 在state manager中有对状态切换动作
2.用抽象类或接口实现父类区别状态就是继承这个父类区别子类
以上面Context为例.我们要修改它建立两个类型实体
第步: 首先建立个父类:
public abstract State{
public abstract void handlepush(Context c);
public abstract void handlepull(Context c);
public abstract void getcolor();
}
父类中思路方法要对应state manager中开关行为在state manager中本例就是Context中有两个开关动作push推和pull拉.那么在状态父类中就要有具体处理这两个动作:handlepush() handlepull(); 同时还需要个获取push或pull结果思路方法getcolor()下面是具体子类实现:
public BlueState extends State{
public void handlepush(Context c){
//根据push思路方法"如果是blue状态切换到green" ;
c.State( GreenState());
}
public void handlepull(Context c){
//根据pull思路方法"如果是blue状态切换到red" ;
c.State( RedState());
}
public abstract void getcolor(){ (Color.blue)}
}
同样其他状态子类实现如blue样第 2步: 要重新改写State manager 也就是本例Context:
public Context{
private Sate state=null; //我们将原来 Color state 改成了新建State state;
//State是用来改变state状态 使用State实现状态切换
pulic void State(State state){
this.state=state;
}
public void push(){
//状态切换细节部分在本例中是颜色变化已经封装在子类handlepush中实现这里无需关心
state.handlepush(this);
//sample要使用state中个切换结果使用getColor()
Sample sample= Sample(state.getColor());
sample.operate();
}
public void pull(){
state.handlepull(this);
Sample2 sample2= Sample2(state.getColor());
sample2.operate();
}
}
至此我们也就实现了Staterefactorying过程以上只是相当简单个例子在实际应用中handlepush或handelpull处理是复杂
最新评论