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

原文:http://blog.csdn.net/hackerain/article/details/7539251

定义:

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

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

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


                                       


其对应的类图如下:

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

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

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

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

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


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

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

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


上面例子的源代码如下:

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

状态模式的优点:

1、结构清晰

避免许多switch 或者if else语句的使用,避免程序的复杂性,提高系统的可维护性

2、遵循设计原则

很好体现开闭原则和单一职责原则,每个状态一个子类,要增加状态就要增加子类,要修改状态,只要修改一个子类就可以

3、封装性非常好

状态变换放置到类的内部实现,外部的调用不用知道类内部如何实现状态和行为的变换

状态模式的使用场景

1、行为随状态改变而改变的场景

这也是状态模式的根本出发点,如权限设计,人员的状态不同即使执行相同的行为结果也会不同,在这种情况下需要考虑使用状态模式

2、条件、分支判断语句的替代者

程序中大量使用switch语句或if判断语句会导致程序结构不清晰,逻辑混乱,使用状态模式可以很好的避免这个问题,它通过扩展子类实现条件的判断处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值