行为型设计模式之状态模式(State)

设计模式之状态模式

这里我们用汽车的运动过程来作为一个示例讲解,首先看一段最初始的代码:

public class State_01 {

    static class Car {
    
        public void start() {
            System.out.println("============启动==========");
        }

        public void run() {
            System.out.println("============行驶==========");
        }

        public void stop() {
            System.out.println("============停止==========");
        }

        public void openDoor() {
            System.out.println("============开门==========");
        }

        public void closeDoor() {
            System.out.println("============关门==========");
        }
    }
}

如上代码,假设汽车状态切换:门关闭状态->门打开状态->启动状态->运行状态->停止状态,在状态切换时,有些行为是不能发生的,所以要做限制,下面按照上面车辆状态切换,来重构以上代码:

public class State_02 {

    static class Car {

        public static final int state_start = 1;
        public static final int state_run = 2;
        public static final int state_stop = 3;
        public static final int state_open = 4;
        public static final int state_close = 5;
        private int state;//当前状态

        public void setState(int state){
            this.state = state;
        }

        public void start() {
            switch (this.state){
                case state_start:break;
                case state_run:break;
                case state_stop:
                    this.startActive();
                    this.setState(state_start);
                    break;
                case state_open:break;
                case state_close:
                    this.startActive();
                    this.setState(state_start);
                    break;
                default: break;
            }
        }

        public void run() {
            switch (this.state){
                case state_start:
                    this.runActive();
                    this.setState(state_run);
                    break;
                case state_run:break;
                case state_stop:
                    this.runActive();
                    this.setState(state_run);
                    break;
                case state_open:break;
                case state_close:break;
                default: break;
            }
        }

        public void stop() {
            switch (this.state){
                case state_start:break;
                case state_run:
                    this.stopActive();
                    this.setState(state_stop);
                    break;
                case state_stop:break;
                case state_open:break;
                case state_close:break;
                default: break;
            }
        }

        public void openDoor() {
            switch (this.state){
                case state_start:break;
                case state_run:break;
                case state_stop:break;
                case state_open:break;
                case state_close:
                    this.openDoorActive();
                    this.setState(state_open);
                    break;
                default: break;
            }
        }

        public void closeDoor() {
            switch (this.state){
                case state_start:
                    break;
                case state_run:break;
                case state_stop:
                    break;
                case state_open:
                    this.closeDoorActive();
                    this.setState(state_close);
                    break;
                case state_close:
                    break;
                default: break;
            }
        }

        private void startActive() {
            System.out.println("============启动==========");
        }

        private void runActive() {
            System.out.println("============行驶==========");
        }

        private void stopActive() {
            System.out.println("============停止==========");
        }

        private void openDoorActive() {
            System.out.println("============开门==========");
        }

        private void closeDoorActive() {
            System.out.println("============关门==========");
        }
    }

    public static void main(String[] args) {
        Car car = new Car();
        car.setState(Car.state_close);
        car.openDoor();
        car.closeDoor();
        car.start();
        car.run();
        car.stop();
    }
}

以上代码的逻辑就是,一开始车门处于关闭状态,这时候可以执行开启车门操作,变为开启状态,然后执行关闭车门操作,变为关闭车门状态,在关闭车门状态下,可以启动汽车,状态变为启动,然后就是行驶,到停止,这就是整个流程。

虽然已经实现功能,但是从以上代码可以知道,这部门代码每个状态切换的方法里面都包含了switch分支,代码显得冗余,尤其如果有新的状态加入,每个switch都要新增一个状态的判断分支,改动过大,所以需要对其进行优化。

就是对状态进行抽象,然后创建子类状态,每个状态类里面都写入各自状态对应的逻辑即可,如下:

public class State_03 {

    static abstract class AbstractState{
        private Context context;

        public void setContext(Context context) {
            this.context = context;
        }

        public abstract void start();

        public abstract void run();

        public abstract void stop();

        public abstract void open();

        public abstract void close();

    }

    static class Context{
        public static final AbstractState startState = new StartState();
        public static final AbstractState runState = new RunState();
        public static final AbstractState stopState = new StopState();
        public static final AbstractState openState = new OpenState();
        public static final AbstractState closeState = new CloseState();

        private AbstractState state;

        public AbstractState getState() {
            return state;
        }

        public void setState(AbstractState state) {
            this.state = state;
            this.state.setContext(this);
        }

        public void start(){
            state.start();
        }

        public void run(){
            state.run();
        }

        public void stop(){
            state.stop();
        }

        public void open(){
            state.open();
        }

        public void close(){
            state.close();
        }
    }

    //启动状态
    static class StartState extends AbstractState{
        @Override
        public void start() {
            System.out.println("================启动================");
        }

        @Override
        public void run() {
            super.context.setState(Context.runState);
            super.context.getState().run();
        }

        @Override
        public void stop() {
            super.context.setState(Context.stopState);
            super.context.getState().stop();
        }

        @Override
        public void open() {

        }

        @Override
        public void close() {

        }
    }

    //行驶状态
    static class RunState extends AbstractState{
        @Override
        public void start() {

        }

        @Override
        public void run() {
            System.out.println("================运行================");
        }

        @Override
        public void stop() {
            super.context.setState(Context.stopState);
            super.context.getState().stop();
        }

        @Override
        public void open() {

        }

        @Override
        public void close() {

        }
    }

    //停止状态
    static class StopState extends AbstractState{
        @Override
        public void start() {
            super.context.setState(Context.startState);
            super.context.getState().start();
        }

        @Override
        public void run() {

        }

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

        @Override
        public void open() {

        }

        @Override
        public void close() {

        }
    }

    //开门状态
    static class OpenState extends AbstractState{
        @Override
        public void start() {

        }

        @Override
        public void run() {

        }

        @Override
        public void stop() {

        }

        @Override
        public void open() {
            System.out.println("================开门=================");
        }

        @Override
        public void close() {
            super.context.setState(Context.closeState);
            super.context.getState().close();
        }
    }

    //启动状态
    static class CloseState extends AbstractState{
        @Override
        public void start() {
            super.context.setState(Context.startState);
            super.context.getState().start();
        }

        @Override
        public void run() {

        }

        @Override
        public void stop() {

        }

        @Override
        public void open() {
            super.context.setState(Context.openState);
            super.context.getState().open();
        }

        @Override
        public void close() {
            System.out.println("================关门=================");
        }
    }

    public static void main(String[] args) {
        Context context = new Context();
        context.setState(Context.closeState);
        context.open();
        context.close();
        context.start();
        context.run();
        context.stop();
    }
}

以上代码主要做了一下动作:

  1. 抽象出状态类,以及抽象方法和依赖的环境类Context(具体调用类)。
  2. 创建一个环境类Context,内部的方法和抽象状态类一样,且可以设置当前状态,在每个方法内部,都是调用当前状态的对应方法。
  3. 实现多个具体的状态类,每个状态类都有具体执行动作方法,以及实现该状态下可以切换到哪些状态方法体,并委托给Context来执行。

以上就是状态模式的一个简单的演变过程,官方对状态模式定义:当一个对象内置状态改变时允许其改变行为,这个对象看起来像改变了其类。

状态模式的优点:

  1. 编码了过多的switch…case或者if…else语句,降低了程序的复杂性,提高了系统可维护性;
  2. 遵循设计原则,开闭原则和单一职责原则。
  3. 封装性好

状态模式的缺点:

状态太多的情况,就会导致子类过多(类膨胀)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值