设计模式学习笔记——状态模式

来源:互联网 发布:mac上装linux虚拟机 编辑:程序博客网 时间:2024/05/17 03:45

定义:

当一个对象内在的状态改变时,允许其改变行为,这个对象看起来像是改变了其类。

状态模式不太好理解,我现在还没有完全理解,这个模式给我的第一印象就是比较乱,给我的感觉好像是两个类互相依赖,①调用②的方法,②调用①的方法,弄的好乱,所以这个状态模式就不用通用类图去描述了,那样会不知所云,还是举一个实际的例子来理解吧。

这个例子是书本上的一个例子,是针对足球队比赛时,根据比分的领先还是落后,来调整其阵型,从而进入相应的状态,其示意图如下:


                                       


其对应的类图如下:

                                                                                  图2  足球对的状态模式类图

解释:可以注意到FootballTeam这个类维护了一个ScoreState对象,表示FootballTeam这个类维护当前的一个状态,通过其中的changeState()方法来切换维护的状态,而改变阵型的方法changeLineUp()这个方法是足球队的行为,它只是调用当前维护状态中的changeLineUp()方法,因为具体的实现是在状态类中取实现的。而在状态类中,也有一个changeState()方法,这个行为的作用是调用FootballTeam中的changeState()方法,来改变FootballTeam所维护的状态。

所以要理解这个交叉的类图,关键要抓住两点:

1、changeLineUp()方法在状态类中实现,而在FootballTeam类中调用;

2、changeState()方法在FootballTeam类中实现,而在状态类中调用;


状态模式有什么好处呢?为什么要这样做呢?

状态模式的本质是将条件语句的各个分支封装起来,从而实现了状态逻辑与动作的分离。当分支很多时,这种模式会给代码的维护带来很大的便利。比如说要增加一个状态,采用分支的话,就要涉及到多个分支的更改。而用状态模式,只需要增加一个新的状态实现类,在这个类中定义这个状态可以切换到哪些状态,这个状态下可以有什么行为,就可以了。当要修改一个状态,只需要修改这个状态类就可以了。

状态模式的封装性非常好,状态变化放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的切换。


上面例子的源代码如下:

public abstract class ScoreState {public abstract void changeLineUp(FootballTeam footballTeam, String score);//这个方法是所有的子类都共有的方法,所以提取到了父类中进行实现protected void changeState(FootballTeam footballTeam, ScoreState state){footballTeam.changeState(state);}}
/* * 平局状态,有两种可能切换的状态: * 1、对手先进球,比分落后,这时调整阵型,状态进入比分落后状态 * 2、己方先进球,比分领先,这时调整阵型,状态进入比分领先状态 */public class DrawState extends ScoreState {@Overridepublic void changeLineUp(FootballTeam footballTeam, String score) {//比分落后if(score=="lag"){ScoreState lagState=new LagState();super.changeState(footballTeam,lagState);System.out.println("比分落后,阵型调整为3-4-3");}else if(score=="ahead"){ScoreState aheadState=new AheadState();super.changeState(footballTeam, aheadState);System.out.println("比分领先,阵型调整为5-4-1");}}}
/* * 比分落后,只有一种可能切换的状态:己方进球扳平比分,比分持平,调整阵型,状态进入持平状态 */public class LagState extends ScoreState {@Overridepublic void changeLineUp(FootballTeam footballTeam, String score) {if(score=="draw"){ScoreState drawState=new DrawState();super.changeState(footballTeam, drawState);System.out.println("比分持平,阵型调整为4-4-2");}}}
/* * 比分领先,只有一种可能切换的状态:对手进球扳平比分,比分持平,调整阵型,状态进入持平状态 */public class AheadState extends ScoreState {@Overridepublic void changeLineUp(FootballTeam footballTeam, String score) {if(score=="draw"){ScoreState drawState=new DrawState();super.changeState(footballTeam, drawState);System.out.println("比分持平,阵型调整为4-4-2");}}}
public class Client {public static void main(String[] args) {String score=null;//定义一个球队,初始状态为持平状态ScoreState drawState=new DrawState();FootballTeam footballTeam=new FootballTeam(drawState);//比分落后score="lag";footballTeam.changeLineUp(score);//扳平比分score="draw";footballTeam.changeLineUp(score);//比分领先score="ahead";footballTeam.changeLineUp(score);}}



原创粉丝点击