当前位置: 首页 > 科技观察

设计模式系列——状态模式

时间:2023-03-19 00:51:02 科技观察

模式定义对于有状态的对象,将复杂的“判断逻辑”提取到不同的状态对象中,让状态对象在其内部状态发生变化时改变自己的行为。状态模式将对象因环境而改变的行为包装在不同的状态对象中,其意图是使一个对象在其内部状态发生变化时改变其行为。下面我们来分析一下它的基本结构和实现方法。模板实现如下:packagecom.niuh.designpattern.state.v1;/***

*statepattern*

*/publicclassStatePattern{publicstaticvoidmain(String[]args){//createenvironmentContextcontext=newContext();//处理请求context.Handle();context.Handle();context.Handle();context.Handle();}}//抽象状态类abstractclassState{publicabstractvoidHandle(Contextcontext);}//具体stateclassAclassConcreteStateAextendsState{publicvoidHandle(Contextcontext){System.out.println("当前状态为A。");context.setState(newConcreteStateB());}}//具体状态classBclassConcreteStateBextendsState{publicvoidHandle(Contextcontext){系统.out。println("当前状态为B。");context.setState(newConcreteStateA());}}//环境类classContext{privateStatestate;//定义环境类的初始状态publicContext(){this.state=newConcreteStateA();}//设置新状态publicvoidsetState(Statestate){this.state=state;}//读取状态publicStategetState(){return(state);}//处理请求publicvoidHandle(){state.Handle(这);}}输出结果如下:当前状态为A当前状态为B当前状态为A当前状态为B已解决问题对象的行为取决于其状态(属性),可以改变根据其状态更改其相关行举例说明模式组合示例概述使用“状态模式”设计一个多线程状态转换程序。分析:多线程有5种状态,分别是新建态、就绪态、运行态、阻塞态、死亡态。每个状态在遇到相关的方法调用或事件触发时都会切换到其他状态。状态转换规则如下所示:现在定义一个抽象状态类(TheadState),然后为上图中的每个状态设计一个具体的状态类,分别是新状态(New)、就绪状态(Runnable)、运行状态运行状态(Running)、阻塞状态(Blocked)和死亡状态(Dead),每个状态都有一个方法来触发它们改变状态。环境类(ThreadContext)首先生成一个初始状态(New),并提供相关的触发方法。下图为线程状态转换程序结构图:使用步骤第一步:定义一个抽象状态类:线程状态abstractclassThreadState{//状态名protectedStringstateName;}第二步:定义具体状态类//具体状态类:新建stateclassNewextendsThreadState{publicNew(){stateName="新状态";System.out.println("当前线程处于:新状态。");}publicvoidstart(ThreadContexthj){System.out.print("调用开始()method-->");if(stateName.equals("新状态")){hj.setState(newRunnable());}else{System.out.println("当前线程不是新状态,并且start()方法不能被调用。");}}}//具体State类:就绪状态classRunnableextendsThreadState{publicRunnable(){stateName="readystate";System.out.println("当前线程处于:就绪状态。”);}publicvoidgetCPU(ThreadContexthj){System.out.print(“获取CPU时间-->”);if(stateName.equals(“就绪状态”)){hj.setState(newRunning());}else{System.out.println("当前线程未处于就绪状态,无法获取CPU。");}}}//具体状态类:运行状态classRunningextendsThreadState{publicRunning(){stateName="运行状态";System.out.println("当前线程处于运行状态。");}publicvoidsuspend(ThreadContexthj){System.out.print("调用suspend()方法-->");if(stateName.equals("运行状态")){hj.setState(newBlocked());}else{System.out.println("当前线程不在运行状态,挂起()方法不能被调用。");}}publicvoidstop(ThreadContexthj){System.out.print("调用stop()方法-->");if(stateName.equals("运行状态")){hj.setState(newDead());}else{System.out.println("当前线程不处于运行状态,无法调用stop()方法。");}}}//具体状态类:阻塞状态classBlockedextendsThreadState{publicBlocked(){stateName="阻塞状态";System.out.println("当前线程在:Blocked状态。”);}publicvoidresume(ThreadContexthj){System.out.print(“调用resume()方法-->”);if(stateName.equals(“阻塞状态”)){hj.setState(newRunnable());}else{System.out.println("当前线程没有阻塞状态,不能调用resume()方法。");}}}//具体状态类:死亡状态classDeadextendsThreadState{publicDead(){stateName="死亡状态";System.out.println("当前线程处于:deadstate.");}}第三步:定义环境类}publicvoidstart(){((New)state).start(this);}publicvoidgetCPU(){((Runnable)state).getCPU(this);}publicvoidsuspend(){((Running)state).suspend(this);}publicvoidstop(){((Running)state).stop(this);}publicvoidresume(){((Blocked)state).resume(this);}}输出结果当前线程处于:新状态。调用start()方法-->当前线程处于:就绪状态。获取CPU时间-->当前线程处于:运行状态。调用suspend()方法-->当前线程处于:阻塞状态。调用resume()方法-->currentthreadisin:readystate.GetCPUTime-->当前线程处于运行状态。调用stop()方法-->当前线程处于:死亡状态。优势状态模式将与特定状态相关的行为本地化到一个状态中,并将不同状态的行为分离开,满足“单一职责原则”,减少对象之间的相互依赖。将不同的状态引入到独立的对象中,将使状态转换更加清晰,降低对象之间的相互依赖性。有利于程序的扩展。根据定义,新的子类很容易添加新的状态和转换。缺点使用状态模式必然会增加系统中类和对象的数量。状态模式的结构和实现都比较复杂,如果使用不当,会导致程序结构和代码混乱。应用场景状态模式通常可以在以下几种情况下考虑。当一个对象的行为取决于它的状态并且它必须在运行时根据状态改变它的行为时,可以考虑使用状态模式。一个操作包含一个巨大的分支结构,这些分支依赖于对象的状态。状态模式的扩展在某些情况下,可能有多个环境对象需要共享一组状态。这时候就需要引入享元模式,将这些具体的状态对象放在一个集合中,供程序共享。结构图如下:分析:分享state模式的区别在于在环境类中增加了一个HashMap来保存相关的状态,需要某个状态的时候可以从中获取。程序代码如下:packagecom.niuh.designpattern.state.v3;importjava.util.HashMap;/***

*Sharedstatepattern*

*/publicclassFlyweightStatePattern{publicstaticvoidmain(String[]args){//创建环境ShareContextcontext=newShareContext();//处理请求context.Handle();context.Handle();context.Handle();context.Handle();}}//抽象状态类abstractclassShareState{publicabstractvoidHandle(ShareContextcontext);}//具体状态类1classConcreteState1extendsShareState{publicvoidHandle(ShareContextcontext){System.out.println("当前状态为:状态1");context.setState(context.getState("2"));}}//具体状态2classConcreteState2extendsShareState{publicvoidHandle(ShareContextcontext){System.out.println("当前状态为:状态2");context.setState(context.getState("1"));}}//环境类classShareContext{privateShareStatestate;privateHashMapstateSet=newHashMap();publicShareContext(){state=newConcreteState1();stateSet.put("1",state);state=newConcreteState2();stateSet.put("2",state);state=getState("1");}//设置新状态publicvoidsetState(ShareStatestate){this.state=state;}//读取状态publicShareStategetState(Stringkey){ShareStates=(ShareState)stateSet.get(key);returns;}//是处理请求publicvoidHandle(){state.Handle(this);}}输出结果如下当前状态为:状态1当前状态为:状态2当前状态为:状态1当前状态为:State2源码中的应用#JDK状态模式:java.util.Iterator#由FacesServlet控制,行为依赖于当前JSF生命周期的阶段(statejavax.faces.lifecycle.LifeCycle#execute()PS:以上代码提交在Github上:https://github.com/Niuh-Study/niuh-designpatterns.git