(8)状态模式

2017-08-20  本文已影响13人  minminaya

定义

当一个对象的内在状态改变是允许改变其行为,这个对象看起来像是改变了其类。关键点在于不同的状态对于同一行为有不同的表现(类似多态:同一个行为具有多个不同表现形式或形态的能力。)

跟策略模式特别像,区别在于策略模式里面的不同策略目的,本质完全不一样,可以彼此独立,可以相互替换(类似数学概率里的互斥事件)。而状态模式不一样,它的行为是平行的,不可替换的(类似对立事件)


使用场景

UML图

状态模式.png

实例


优点

缺点


例子

用电视机作为例子,电视机升高音量降低音量的功能,而已打开电源的电视机和已关闭的电视机是电磁炉的2种状态(不是开的就是关的)

  1. 假如未用状态模式前,应该是用的if-else语句判断状态然后执行方法,具体如下
/** 普通情况,if-else判断的
 * Created by Niwa on 2017/8/20.
 */
public class TvControllerNomal {
    /**
     * 关机状态标志
     */
    private final static int POWER_OFF = 2;
    /**
     * 开机状态标志
     */
    private final static int POWER_ON = 1;
    /**
     * 默认状态
     */
    private int mState = POWER_OFF;

    public void powerOn() {
        if (mState == POWER_OFF) {
            mState = POWER_ON;
            System.out.println("开机啦");
        }
    }

    public void powerOff() {
        if (mState == POWER_ON) {
            mState = POWER_OFF;
            System.out.println("关机啦");
        }
    }

    public void nextChannel() {
        if (mState == POWER_ON) {
            System.out.println("下一频道");
        }
    }
    public void preChannel() {
        if (mState == POWER_ON) {
            System.out.println("上一频道");
        }
    }
    public void turnUp() {
        if (mState == POWER_ON) {
            System.out.println("调高音量");
        }
    }


    public static void main(String[] args){
        TvControllerNomal mTvControllerNomal = new TvControllerNomal();
        mTvControllerNomal.powerOn();
        mTvControllerNomal.nextChannel();

        mTvControllerNomal.powerOff();
        mTvControllerNomal.nextChannel();
    }

}

执行main方法后,输出信息如下

开机啦
下一频道
关机啦

以下逐渐改造该类为状态模式

  1. 定义电视机状态接口
/**
 * 电视功能接口,定义了电视操作的函数
 * Created by Niwa on 2017/8/20.
 */
public interface TvState {
    void nextChannel();

    void prevChannel();

    void turnUp();

    void turnDown();
}

定义电视机的几个功能

  1. 分别书写电视机的两种状态,开机状态下的功能和关机状态下的功能,开机情况下能操作所有功能,关机情况下,功能无响应
/** 关机状态
 * Created by Niwa on 2017/8/20.
 */
public class PowerOffState  implements TvState{
    @Override
    public void nextChannel() {

    }

    @Override
    public void prevChannel() {

    }

    @Override
    public void turnUp() {

    }

    @Override
    public void turnDown() {

    }
}


/** 关机状态
 * Created by Niwa on 2017/8/20.
 */
public class PowerOnState implements TvState{
    @Override
    public void nextChannel() {
        System.out.println("下一频道");
    }

    @Override
    public void prevChannel() {
        System.out.println("上一频道");
    }

    @Override
    public void turnUp() {
        System.out.println("音量加");
    }

    @Override
    public void turnDown() {
        System.out.println("音量剪");
    }
}
  1. 定义电视的状态接口
/** 电视状态接口
 * Created by Niwa on 2017/8/20.
 */
public interface PowerController {
    void powerOn();
    void powerOff();
}

  1. 书写状态的控制器,实现电视机的状态的接口
/** 电视遥控器,类似于经典状态模式中的Context
 * Created by Niwa on 2017/8/20.
 */
public class TvController implements PowerController {
    TvState mTvState;

    public void setmTvState(TvState mTvState) {
        this.mTvState = mTvState;
    }

    @Override
    public void powerOn() {
        setmTvState(new PowerOnState());
        System.out.println("开机啦");
    }

    @Override
    public void powerOff() {
        setmTvState(new PowerOffState());
        System.out.println("关机啦");
    }

    public void nextChannel() {
        mTvState.nextChannel();
    }

    public void prevChannel() {
        mTvState.prevChannel();
    }

    public void turnUp() {
        mTvState.turnUp();
    }

    public void turnDown() {
        mTvState.turnDown();
    }
}

  1. 最后在main函数中测试
public static void main(String[] args) {
        TvController tvController = new TvController();
        tvController.powerOn();
        tvController.nextChannel();
        tvController.turnUp();
        tvController.powerOff();
        //调高音量,此时不会生效
        tvController.turnUp();
    }


打印结果:

开机啦
下一频道
音量加
关机啦

UML图

电视机状态模式

定义一个电视机的功能的接口,然后分别对应电视机的开关两个状态实现其功能,然后用TvController(相当于电视机遥控器了)来注入两种状态的类,在TvController具体执行所需要的功能,跟状态模式UML差不多,但意图却完全不一样,策略模式是让用户指定更换的策略算法,而状态模式是状态在满足一定条件下的自动更换,用户无法指定状态,最多只能设置初始状态。

源代码:DesignPattern


参考

《Android源码设计模式解析与实战读书》
各大佬博客


end

上一篇 下一篇

猜你喜欢

热点阅读