IF-ELSE方法本来以为写一个简单的类型翻译器不会花太多时间,但是真正做到的时候才发现要注意的点太多了。首先是处理容器的打开和关闭,这需要使用栈来保存期望的下一个字符类型,然后将栈顶的字符类型与当前处理的字符进行比较,判断结果分析。另外需要注意的是,在类型嵌套的情况下,当内部嵌套容器被解析为外部容器的元素时,需要修改外部容器的期望字符。而且,作为相对于Set和List的特殊容器,Map也需要处理它的左右元素。同时,我们也不能忘记处理各种异常,比如未知字符、容器中的原始类型、错误关闭的容器等。这些逻辑混合在一起增加了复杂性。通常,代码一次就写得很顺利。找了几个特例验证后,往往有没有考虑到的点。你觉得解决这个点就好了。殊不知,这个问题点的解决又引发了另一个问题。最后修修补补了很多次,终于把代码写完了,连优化的念头都没有了,担心引入新的问题。更多Java核心技术教程:https://github.com/javastacks/javastack,一起来学习吧。最终伪代码如下:publicStringparseToFullType()throwsIllegalStateException{StringBuildersb=newStringBuilder();for(;;this.scanner.next()){CharactercurrentChar=scanner.current();if(currentChar=='\uFFFF'){returnsb.toString();}if(isCollection()){if(CollectionEnd()){dealCollectionEleEnd();}else{thrownewIllegalStateException("unexpectedchar'"+currentChar+"'atposition"+scanner.getIndex());}}elseif(isWrapperType()){dealSingleEleEnd();}elseif(parseStart()){if(collectionStart()){putCollecitonExpectEle()}}else{thrownewIllegalStateException("unknownchar'"+currentChar+"'atposition"+scanner.getIndex());}}状态机方法是不是看起来很乱,各个方法中的条件判断语句还没列出来。这么多逻辑混在一起,问题是很难改变,因为你不知道改变会影响到其他哪些逻辑。面对这种问题,当然有一套代码设计经验总结,反复使用,为大多数人所知,归类整理,就是状态机。状态机有限状态机(finite-statemachine,缩写:FSM),也称为有限状态自动化(缩写:FSA),简称状态机,是对有限数量的状态和之间的转换的表示这些状态和动作等行为的数学计算模型。例如,在我们的生活中,在路上开车就像在维护一个状态机。遇到红灯停车喝酒,红灯后继续行驶,遇到黄灯减速慢行。在实现状态机之前,首先要定义四个主体:State状态:状态是系统在其生命周期中某一时刻的运行状态。例如,在驾驶的例子中,状态包括三种状态:正常速度驾驶、停车和低速驾驶。事件事件:事件是在特定时刻施加于系统的信号。在上面的例子中,一个事件指的是红灯、绿灯和黄灯。所有状态的改变都依赖于事件,但事件也可能导致状态不改变。比如正常行驶遇到绿灯,就不需要反应。TransformationTransition:一个transformation是系统在一个事件发生后,如上例中的减速、停车或加速等,将进行的状态改变。Action动作:动作也是事件发生后系统的反应。不同之处在于该操作不会更改系统状态。比如开车遇到红灯停车喝水,不会影响系统状态。把状态机的四大要素抽取出来后,状态和事件就可以轻松解耦了。对于状态分裂,我还是分析一下自己的需求。首先画出状态变化图,从整体上把握状态之间的关系。通过上图一步步拆解状态机:1、首先确定状态。我定义了八种基本状态:Start/SetStart/SetEle/ListStart/ListEel/MapStart/MapLeft/MapRight。由于一次只解析一种类型,容器关闭就意味着解析结束,所以没有为每个容器设置结束状态。并且由于有状态嵌套的存在,一个状态不能表达状态机的确切状态,需要用一个栈来存储整体的解析状态。我用这个堆栈来表示End状态并省略另一个状态。2.再次拆分事件。事件是扫描的每个字符。由于字符的类型很多,对integer和double、String和Long的处理没有区别,我把事件类型抽象成wrapping类型元素(WRAPPED_ELE)、原始类型元素(PRIMITIVE_ELE)、MAP、List和设置五。3.变化和动作是事件发生后系统的反应。在我的需求中,我需要更改分析状态并保存结构结果。这里我将它们整体抽象为一个事件处理接口,如:publicinterfaceStateHandler{/***@paramevent待处理事件*@paramstates系统整体状态*@paramresult分析结果*/voidhandle(Eventevent,Stack
