设计模式笔记--状态模式

来源:互联网 发布:linux locate命令 编辑:程序博客网 时间:2024/05/29 10:25

常用设计模式有23中,分为:

创建型模式(主要用于创建对象)

1、单例模式    2、工厂方法模式    3、抽象工厂模式    4、建造者模式     5、原型模式 
行为型模式 (主要用于描述对象或类是怎样交互和怎样分配职责)

1、模板方法模式  2、中介者模式  3、命令模式    4、责任链模式   5、策略模式   6、迭代器模式  

7、观察者模式      8、备忘录模式   9、访问者模式   10、状态模式  11、解释器模式

结构型模式(主要用于处理类或对象的组合)

1、代理模式  2、装饰模式   3、适配器模式   4、组合模式   5、外观模式(门面模式)   6、享元模式   7、桥梁模式



状态模式 

其定义如下:
当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。  

状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象对应的类发生了改变一样  



状态模式中的3个角色。

● State——抽象状态角色
接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换。

● ConcreteState——具体状态角色
每一个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。

● Context——环境角色
定义客户端需要的接口,并且负责具体状态的切换。  


状态模式相对来说比较复杂,它提供了一种对物质运动的另一个观察视角,通过状态变更促使行为的变化  


抽象环境角色,如代码清单26-14所示。
<span style="font-size:18px;">代码清单26-14 抽象环境角色public abstract class State {//定义一个环境角色,提供子类访问protected Context context;//设置环境角色public void setContext(Context _context){this.context = _context;}//行为1public abstract void handle1();//行为2public abstract void handle2();}</span>
抽象环境中声明一个环境角色,提供各个状态类自行访问,并且提供所有状态的抽象行为,由各个实现类实现。


具体环境角色如代码清单26-15所示。
<span style="font-size:18px;">代码清单26-15 环境角色public class ConcreteState1 extends State {@Overridepublic void handle1() {//本状态下必须处理的逻辑}@Overridepublic void handle2() {//设置当前状态为stat2super.context.setCurrentState(Context.STATE2);//过渡到state2状态,由Context实现super.context.handle2();}}</span>
<span style="font-size:18px;">public class ConcreteState2 extends State {@Overridepublic void handle1() {//设置当前状态为state1super.context.setCurrentState(Context.STATE1);//过渡到state1状态,由Context实现super.context.handle1();}@Overridepublic void handle2() {//本状态下必须处理的逻辑}}</span>
具体环境角色有两个职责:处理本状态必须完成的任务,决定是否可以过渡到其他状态。


我们再来看环境角色,如代码清单26-16所示。
<span style="font-size:18px;">代码清单26-16 具体环境角色public class Context {//定义状态public final static State STATE1 = new ConcreteState1();public final static State STATE2 = new ConcreteState2();//当前状态private State CurrentState;//获得当前状态public State getCurrentState() {return CurrentState;}//设置当前状态public void setCurrentState(State currentState) {this.CurrentState = currentState;//切换状态this.CurrentState.setContext(this);}//行为委托public void handle1(){this.CurrentState.handle1();}public void handle2(){this.CurrentState.handle2();}}</span>
环境角色有两个不成文的约束:

● 把状态对象声明为静态常量,有几个状态对象就声明几个静态常量。

● 环境角色具有状态抽象角色定义的所有行为,具体执行使用委托方式。


我们再来看场景类如何执行,如代码清单26-17所示。
<span style="font-size:18px;">public class Client {public static void main(String[] args) {//定义环境角色Context context = new Context();//初始化状态context.setCurrentState(new ConcreteState1());//行为执行context.handle1();context.handle2();}}  </span>

隐藏了状态的变化过程,它的切换引起了行为的变化。对外来说,我们只看到行为的发生改变,而不用知道是状态变化引起的。  


优点  

● 结构清晰  
避免了过多的switch...case或者if...else语句的使用,避免了程序的复杂性,提高系统的可维护性。 
 
● 遵循设计原则  

● 封装性非常好  


缺点  

子类会太多,也就是类膨胀。  


使用场景  

● 行为随状态改变而改变的场景 

● 条件、分支判断语句的替代者


注意事项  

状态模式适用于当某个对象在它的状态发生改变时,它的行为也随着发生比较大的变化,也就是说在行为受状态约束的情况下可以使用状态模式,而且使用时对象的状态最好不要超过5个。  


建造模式+状态模式会起到非常好的封装作用。  


实例 电梯 






在类图中,定义了一个LiftState抽象类,声明了一个受保护的类型Context变量,这个是串联各个状态的封装类。封装的目的很明显,就是电梯对象内部状态的变化不被调用类知晓,也就是迪米特法则  


抽象电梯状态  
<span style="font-size:18px;">代码清单26-7 抽象电梯状态public abstract class LiftState{//定义一个环境角色,也就是封装状态的变化引起的功能变化protected Context context;public void setContext(Context _context){this.context = _context;}//首先电梯门开启动作public abstract void open();//电梯门有开启,那当然也就有关闭了public abstract void close();//电梯要能上能下,运行起来public abstract void run();//电梯还要能停下来public abstract void stop();}</span>


敞门状态的实现类  
<span style="font-size:18px;">代码清单26-8 敞门状态public class OpenningState extends LiftState {//开启当然可以关闭了,我就想测试一下电梯门开关功能@Overridepublic void close() {//状态修改super.context.setLiftState(Context.closeingState);//动作委托为CloseState来执行super.context.getLiftState().close();}//打开电梯门@Overridepublic void open() {System.out.println("电梯门开启...");}//门开着时电梯就运行跑,这电梯,吓死你!@Overridepublic void run() {//do nothing;}//开门还不停止?public void stop() {//do nothing;}}</span>


关闭状态  
<span style="font-size:18px;">public class ClosingState extends LiftState {//电梯门关闭,这是关闭状态要实现的动作@Overridepublic void close() {System.out.println("电梯门关闭...");}//电梯门关了再打开@Overridepublic void open() {super.context.setLiftState(Context.openningState); //置为敞门状态super.context.getLiftState().open();}//电梯门关了就运行,这是再正常不过了@Overridepublic void run() {super.context.setLiftState(Context.runningState); //设置为运行状态super.context.getLiftState().run();}//电梯门关着,我就不按楼层@Overridepublic void stop() {super.context.setLiftState(Context.stoppingState); //设置为停止状态super.context.getLiftState().stop();}}</span>
另外两个实现类相识,不一一赘述


上下文类  
<span style="font-size:18px;">代码清单26-9 上下文类public class Context {//定义出所有的电梯状态public final static OpenningState openningState = new OpenningState();public final static ClosingState closeingState = new ClosingState();public final static RunningState runningState = new RunningState();public final static StoppingState stoppingState = new StoppingState();//定义一个当前电梯状态private LiftState liftState;public LiftState getLiftState() {return liftState;}public void setLiftState(LiftState liftState) {this.liftState = liftState;//把当前的环境通知到各个实现类中this.liftState.setContext(this);}public void open(){this.liftState.open();}public void close(){this.liftState.close();}public void run(){this.liftState.run();}public void stop(){this.liftState.stop();}}</span>


模拟场景类  
<span style="font-size:18px;">public class Client {public static void main(String[] args) {Context context = new Context();context.setLiftState(new ClosingState());context.open();context.close();context.run();context.stop();}}</span>




 

0 0
原创粉丝点击