设计模式学习之屡屡清楚状态模式

定义:

当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。状态模式的核心是封装,由于对象内部状态的改变,从而使这个类改变了其行为,看起来就像是换了一个类一样。

三个角色:

  • State抽象状态角色

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

  • ConcreteState具体状态角色

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

  • Context环境角色

定义客户端需要的接口,并且负责具体状态的切换。

代码示例:

package com.statechanges;

/**
 * 环境角色
 */
public class Context {
    //电梯状态
    public final static OpenningState openningState = new OpenningState();
    public final static CloseingState closeingState = new CloseingState();
    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();
    }
}

package com.statechanges;

/**
 * 抽象电梯状态类
 */
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();
}

package com.statechanges;

public class OpenningState extends LiftState {
    //打开电梯
    @Override
    public void open() {
        System.out.println("电梯门开启");
    }

    @Override
    public void close() {
        //状态修改
        super.context.setLiftState(Context.closeingState);
        //动作委托为CloseState来执行
        super.context.getLiftState().close();
    }

    @Override
    public void run() {

    }

    @Override
    public void stop() {

    }
}

package com.statechanges;

public class CloseingState extends LiftState {
    //电梯门关了再打开
    @Override
    public void open() {
        super.context.setLiftState(Context.openningState);//设置为敞门状态
        super.context.getLiftState().open();

    }

    @Override
    public void close() {
        System.out.println("电梯门关闭");
    }
    //电梯门关了,电梯开始运行
    @Override
    public void run() {
        super.context.setLiftState(Context.runningState);
        super.context.getLiftState().run();
    }

    @Override
    public void stop() {
        super.context.setLiftState(Context.stoppingState);
        super.context.getLiftState().stop();
    }
}

package com.statechanges;

public class RunningState extends LiftState {
    //电梯运行期间,电梯门是关着的
    @Override
    public void open() {

    }

    @Override
    public void close() {

    }

    @Override
    public void run() {
        System.out.println("电梯正在上下运行");
    }

    @Override
    public void stop() {
        super.context.setLiftState(Context.stoppingState);
        super.context.getLiftState().stop();
    }
}

package com.statechanges;

public class StoppingState extends LiftState {
    @Override
    public void open() {
        super.context.setLiftState(Context.openningState);//设置为敞门状态
        super.context.getLiftState().open();
    }

    @Override
    public void close() {

    }

    @Override
    public void run() {
        super.context.setLiftState(Context.runningState);
        super.context.getLiftState().run();
    }

    @Override
    public void stop() {
        System.out.println("电梯停止了");
    }
}

package com.statechanges;

/**
 * 状态模式
 */
public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        context.setLiftState(new CloseingState());
        context.open();
        context.close();
        context.run();
        context.stop();
    }
}

//打印结果
电梯门开启
电梯门关闭
电梯正在上下运行
电梯停止了

总结:

优点:

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

遵循设计原则:很好地体现了开闭原则和单一职责原则,每个状态都是一个子类,增加状态就要增加子类,修改状态,只修改一个子类就可以。

封装性非常好:这也是状态模式的基本要求,状态变换放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换。

缺点:

随着状态的增多,子类会变得更多,所以需要权衡状态值得设定,如果无法限制可以预先在数据库存储,这样就更有利于状态模式的使用。

摘自《设计模式之禅》

你可能感兴趣的:(Java设计模式)