现在遇到了这样一个场景:要将一系列操作自动化,其中涉及到一些状态以及状态的转移。状态有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 }
第二版修复了第一版出现的问题,所有实现功能的代码只出现了一次,,但还是不够好,抽象类的作用已经发生了变化,和接口有重叠。鉴于状态不会再有变动,接口可以去掉了,留抽象类足矣。
感觉还是不够好,写得很垃圾,以后再改吧,现在这样足够能用了,也没有多线程场景,不过以后要是有的话问题可就大了。
欢迎提出意见指正
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法