经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
状态模式
来源:cnblogs  作者:纳兰小依  时间:2019/10/21 8:58:07  对本文有异议

      状态模式,顾名思义,重点关注对象的各种状态。状态模式将对象的每一种状态独立成类,同时将对象的行为委托给对应的状态类执行。它的优点在于,当需要增加或者减少对象的状态时,只需要增加减少状态类,并修改少量的代码就能实现。

      本文将采用状态模式和非状态模式分别实现同一个例子,以讲解状态模式的用法以及使用状态模式的好处。

      例子很简单,我们想用程序来模拟人在不同负重下的行走和奔跑行为,负重越少,行走和奔跑就越轻松;负重越多行走和奔跑则愈发费劲,甚至根本就跑不动。

1. 普通方式实现人在不同负重下的行走和奔跑行为

      首先采用最平常的方式来实现行走和奔跑的设计:

  1. public class Human {
  2. private double weight; //体重
  3. private double weightBearing; //负重
  4.  
  5. public Human(double weight){
  6. this.weight = weight;
  7. }
  8. public void setWeightBearing(double weightBearing){
  9. this.weightBearing = weightBearing;
  10. }
  11. public double getRate(){
  12. return weightBearing / weight;
  13. }
  14. public void walk(){
  15. double rate = getRate();
  16. if(rate < 0.2){
  17. System.out.println("轻轻松松地走。。。");
  18. }else if(rate < 0.6){
  19. System.out.println("气喘吁吁地走。。。");
  20. }else{
  21. System.out.println("只能慢慢走。。。");
  22. }
  23. }
  24. public void run(){
  25. double rate = getRate();
  26. if(rate < 0.2){
  27. System.out.println("一路小跑。。。");
  28. }else if(rate < 0.6){
  29. System.out.println("象征性地跑。。。");
  30. }else{
  31. System.out.println("跑不动。。。");
  32. }
  33. }
  34. }

      然后测一测代码的效果:

  1. public class StatePatternTest {
  2. public static void main(String[] args){
  3. StatePatternTest test = new StatePatternTest();
  4. test.normalTest();
  5. }
  6. public void normalTest(){
  7. Human human = new Human(150);
  8. human.walk();
  9. human.run();
  10. human.setWeightBearing(50);
  11. human.walk();
  12. human.run();
  13. human.setWeightBearing(100);
  14. human.walk();
  15. human.run();
  16. }
  17. }

      输出如下:

  1. 轻轻松松地走。。。
  2. 一路小跑。。。
  3. 气喘吁吁地走。。。
  4. 象征性地跑。。。
  5. 只能慢慢走。。。
  6. 跑不动。。。

      代码看起来没有问题,不过我们发现,负重比在大于60%这个区间还可以进一步细化,因为负重越大,对体能影响越大,这个时候每增加10%可能都会有不一样的结果。对于这样的细化要求,我们需要修改上面每个方法里的分支语句,并且随着以后的细化需求越来越多,分支会越来越长,不利于维护。

      通过观察分析,我们发现,不同的区间对应不同的行为,可以根据区间进行划分,每个区间实现自己的walk()和fun()方法,对于Human对象来说,不需要知道现在是处在哪个负重区间,只需要将行为委托给区间对象去处理就行了。在这里,我们称不同的区间为不同的状态,所有的状态实现或者继承同一个State对象。

      接下来,我们准备使用状态模式重新实现行走和奔跑的设计,在继续进行下去之前,先给出状态模式的定义。

2. 状态模式的定义

状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

      定义的第一部分说的是状态改变的时候,对象的行为也会随之改变,在我们的例子中,负重改变时,行走和奔跑的行为会有不同的表现;定义的第二部分是说,状态改变的时候对象发生对应的改变,在外界看起来,好像是在跟一个新的类打交道,实际上我们知道,对象还是那个对象,只是底层的实现改变了而已。

3. 采用状态模式的实现

      下面将使用状态模式来重新设计,首先定义统一的状态接口State:

  1. public interface State {
  2. void walk();
  3. void run();
  4. }

      根据不同的负重定义三种负重状态:

  1. //轻度负重类
  2. public class SlightlyOverWeighted implements State {
  3. private SmartHuman human;
  4. public SlightlyOverWeighted(SmartHuman human){
  5. this.human = human;
  6. }
  7. @Override
  8. public void walk() {
  9. if(human.getRate() < 0.2){
  10. System.out.println("轻轻松松地走。。。");
  11. }else{
  12. human.setState(new MiddleOverWeighted(human));
  13. human.walk();
  14. }
  15. }
  16. @Override
  17. public void run() {
  18. if(human.getRate() < 0.2){
  19. System.out.println("一路小跑。。。");
  20. }else{
  21. human.setState(new MiddleOverWeighted(human));
  22. human.run();
  23. }
  24. }
    }
  1. //中度负重类
  2. public class MiddleOverWeighted implements State{
  3. private SmartHuman human;
  4. public MiddleOverWeighted(SmartHuman human){
  5. this.human = human;
  6. }
  7. @Override
  8. public void walk() {
  9. if(human.getRate() < 0.6){
  10. System.out.println("气喘吁吁地走。。。");
  11. }else{
  12. human.setState(new OverWeighted(human));
  13. human.walk();
  14. }
  15. }
  16. @Override
  17. public void run() {
  18. if(human.getRate() < 0.6){
  19. System.out.println("象征性地跑。。。");
  20. }else{
  21. human.setState(new OverWeighted(human));
  22. human.run();
  23. }
  24. }
  25. }
  1. //超重类
  2. public class OverWeighted implements State{
  3. private SmartHuman human;
  4. public OverWeighted(SmartHuman human){
  5. this.human = human;
  6. }
  7. @Override
  8. public void walk() {
  9. System.out.println("只能慢慢走。。。");
  10. }
  11. @Override
  12. public void run() {
  13. System.out.println("跑不动。。。");
  14. }
  15. }

      下面测试一下采用状态模式的实现:

  1. public class StatePatternTest {
  2. public static void main(String[] args){
  3. StatePatternTest test = new StatePatternTest();
  4. test.statePatternTest();
  5. }
  6. public void statePatternTest(){
  7. SmartHuman human = new SmartHuman(150);
  8. human.walk();
  9. human.run();
  10. human.setWeightBearing(50);
  11. human.walk();
  12. human.run();
  13. human.setWeightBearing(100);
  14. human.walk();
  15. human.run();
  16. }
  17. }

      输出为:

  1. 轻轻松松地走。。。
  2. 一路小跑。。。
  3. 气喘吁吁地走。。。
  4. 象征性地跑。。。
  5. 只能慢慢走。。。
  6. 跑不动。。。

4. 总结

      新的测试类几乎与之前的测试一模一样,而且结果也符合预期。当我们想喜欢负重状态时,只需要增加对应的状态类,然后修改相邻状态类的少量代码即可。从上面的代码总结出状态模式的类图结构如下:

 

 

 5. 参考文献

<<Head First设计模式>>

<<大话设计模式>>

原文链接:http://www.cnblogs.com/NaLanZiYi-LinEr/p/11704960.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号