• 状态模式的场景应用


    现在遇到了这样一个场景:要将一系列操作自动化,其中涉及到一些状态以及状态的转移。状态有4种:初始状态0,第一步A,第二步B,第三步C。其中这几个状态间的转移关系就略去了,抽象出来是这样的:无论从哪种状态转移到目标状态,做出的行为都是表示“到目标状态”所做的行为,即与上一步状态无关,只与目标状态有关。故使用状态模式实现。简单说明问题的代码如下:

    状态管理:

     1 public class StateManager {
     2     private State state;
     3     private StateManager() {}
     4     public StateManager(State state) {this.state = state;}
     5     public StateManager(String state) {... // 根据状态码初始化云云}
     6     public State getState() {return state;}
     7     public void setState(State state) {this.state = state;}
     8     public void to0() {state.to0(this);}
     9     public void toA() {state.toA(this);}
    10     public void toB() {state.toB(this);}
    11     public void toC() {state.toC(this);}
    12 }

    状态接口:

    1 public interface State {
    2     void to0(StateManager sm);
    3     void toA(StateManager sm);
    4     void toB(StateManager sm);
    5     void toC(StateManager sm);
    6 }

    抽象父类:

    1 public abstract class AbstractState implement State {
    2     public void to0(StateManager sm) { throw new UnsupportedOperationException();}
    3     public void toA(StateManager sm) { throw new UnsupportedOperationException();}
    4     public void toB(StateManager sm) { throw new UnsupportedOperationException();}
    5     public void toC(StateManager sm) { throw new UnsupportedOperationException();}
    6 }

    具体子类:

     1 public class State0 extends AbstractState {
     2     public void toA(StateManager sm) { print("toA");sm.setState(new StateA()); } // 允许转移到A
     3 }
     4 
     5 public class StateA extends AbstractState {
     6     public void to0(StateManager sm) { print("to0");sm.setState(new State0()); } // 允许重置
     7     public void toB(StateManager sm) { print("toB");sm.setState(new StateB()); } // 允许转移到B
     8     public void toC(StateManager sm) { print("toC");sm.setState(new StateC()); } // 允许转移到C
     9 }
    10 
    11 public class StateB extends AbstractState {
    12     public void to0(StateManager sm) { print("to0");sm.setState(new State0()); } // 允许重置
    13     public void toC(StateManager sm) { print("toC");sm.setState(new StateC()); } // 允许转移到C
    14 }
    15 
    16 public class StateC extends AbstractState {
    17     public void to0(StateManager sm) { print("to0");sm.setState(new State0()); } // 允许重置
    18     public void toC(StateManager sm) { print("toC_Again"); } // 覆盖,走另一个逻辑
    19 }

    简单举例吧,状态转移就点到为止。至此一个由基本的状态模式改造的模型就写完了,一个抽象父类提供一个默认抛出不支持异常的方法,子类需要实现转移到哪个状态,就重写哪个方法。问题很明显,代码冗余很严重。发现toC方法写错了,我要改3个地方。Java容器类库里AbstractList里提供默认抛出不支持操作异常的目的是避免接口爆炸,不能随随便便就抄过来的。但是,这个逻辑还是有应用在这个场景下的味道在里面的,只不过用反了。不应该是给无能者赋予能力,而是给健全者予以阉割!第二版更改如下:

    抽象父类:

    1 public abstract class AbstractState implement State {
    2     public void to0(StateManager sm) { print("to0");sm.setState(new State0()); } // 允许重置
    3     public void toA(StateManager sm) { print("toA");sm.setState(new StateA()); } // 允许转移到A
    4     public void toB(StateManager sm) { print("toB");sm.setState(new StateB()); } // 允许转移到B
    5     public void toC(StateManager sm) { print("toC");sm.setState(new StateC()); } // 允许转移到C
    6 }

    具体子类:

     1 public class State0 extends AbstractState {
     2     public void to0(StateManager sm) { throw new UnsupportedOperationException();} // 禁止的状态转移阉割掉
     3     public void toB(StateManager sm) { throw new UnsupportedOperationException();} // 禁止的状态转移阉割掉
     4     public void toC(StateManager sm) { throw new UnsupportedOperationException();} // 禁止的状态转移阉割掉
     5 }
     6  
     7 public class StateA extends AbstractState {
     8     public void toA(StateManager sm) { throw new UnsupportedOperationException();} // 禁止的状态转移阉割掉
     9 }
    10 
    11 public class StateB extends AbstractState {
    12     public void toA(StateManager sm) { throw new UnsupportedOperationException();} // 禁止的状态转移阉割掉
    13     public void toB(StateManager sm) { throw new UnsupportedOperationException();} // 禁止的状态转移阉割掉
    14 }
    15 
    16 public class StateC extends AbstractState {
    17     public void toA(StateManager sm) { throw new UnsupportedOperationException();} // 禁止的状态转移阉割掉
    18     public void toB(StateManager sm) { throw new UnsupportedOperationException();} // 禁止的状态转移阉割掉
    19     public void toC(StateManager sm) { print("toC_Again"); } // 覆盖,走另一个逻辑
    20 }

    第二版修复了第一版出现的问题,所有实现功能的代码只出现了一次,,但还是不够好,抽象类的作用已经发生了变化,和接口有重叠。鉴于状态不会再有变动,接口可以去掉了,留抽象类足矣。

    感觉还是不够好,写得很垃圾,以后再改吧,现在这样足够能用了,也没有多线程场景,不过以后要是有的话问题可就大了。

    欢迎提出意见指正

  • 相关阅读:
    6.linux下指定项目使用特定jdk
    5.linux 执行shell报bad interpreter:No such file or directory错误
    定时任务基础版本
    同一台电脑安装两个jdk切换问题
    接口如何设计?安全如何保证?签名如何实现?防重如何实现?
    spring boot常见get 、post请求参数处理
    bat例子
    1.Volatile关键字详解
    1.linux目录
    解析xml报文,xml与map互转
  • 原文地址:https://www.cnblogs.com/cachedking/p/8061734.html
Copyright © 2020-2023  润新知