把书读薄 | 《设计模式之美》设计模式与范式(行为型-状态模式)(上)

简介: 本文对应设计模式与范式:行为型(64),状态模式 (State Pattern),描述了对象 状态变化 及如何在每种状态下表现出不同的 行为~

0x1、定义


原始定义


允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了自己的类一样。


简单点说


让一个对象通过一系列状态的变化来控制行为的变化。


状态模式策略模式 极其相似,可通过内在差别进行区分:


  • 策略模式将具体策略类暴露出去,调用者需了解每种策略的不同之处以便正确使用,封装的是不同算法,算法间没有交互,以达到算法可以自由切换的目的。


  • 状态模式状态的改变是由其内部条件来改变的,与外界无关,封装的是不同状态,以达到状态切换行为随之切换的目的。


0x2、写个简单例子


有home键的Android机为例,按下home键,处于不同状态有不同的行为:


  • 关机状态 → 没有反应;


  • 开机后首次启动 → 密码解锁;


  • 非首次启动 → 密码解锁或指纹解锁;


  • 启动后 → 返回主界面


不使用状态模式实现一波:


public class StateTest {
    private static int state = 0;
    private final static int CLOSE = 0; // 关机状态
    private final static int FIRST_BOOT = 1;   // 首次启动
    private final static int NOT_FIRST_BOOT = 2;    // 非首次启动
    private final static int AFTER_BOOT = 3;    // 启动后
    private static void clickHome() {
        if(state == CLOSE) {
            System.out.println("处于关机状态,没有反应");
        } else if(state == FIRST_BOOT) {
            System.out.println("首次启动。可以进行密码解锁");
        } else if(state == NOT_FIRST_BOOT) {
            System.out.println("非首次启动,可以进行密码或指纹解锁");
        } else if(state == AFTER_BOOT) {
            System.out.println("启动状态,返回主界面");
        }
    }
    public static void main(String[] args) {
        state = CLOSE;
        clickHome();
        state = FIRST_BOOT;
        clickHome();
        state = NOT_FIRST_BOOT;
        clickHome();
        state = AFTER_BOOT;
        clickHome();
    }
}


代码运行结果如下


网络异常,图片无法展示
|


如果需要增加一种状态,如处于fastboot模式,状态定义要写一个,然后if-else加一个判断;还有,不止处理Home键,还有音量键、电源键,又得定义几个函数,然后复制一波这个if-else,试试用状态模式实现一波。


// 抽象状态
public abstract class State {
    protected StateContext context;
    public void setContext(StateContext context) { this.context = context; }
    abstract void onHomeClick();
    abstract void onPowerClick();
    abstract void onVolumeAscClick();
    abstract void onVolumeDescClick();
}
// 具体状态 → 关机状态
public class CloseState extends State {
    @Override public void onHomeClick() { System.out.println("处于关机状态,按Home键没有反应"); }
    @Override void onPowerClick() {
        System.out.println("手机开机");
        context.setState(FirstBootState.class);
        context.setScreenOn(true);
        context.getState().onHomeClick();
    }
    @Override void onVolumeAscClick() { System.out.println("处于关机状态,按音量+没反应"); }
    @Override void onVolumeDescClick() {  System.out.println("处于关机状态,按音量-没反应"); }
}
// 具体状态 → 第一次启动状态
public class FirstBootState extends State {
    @Override public void onHomeClick() {
        System.out.println("首次启动,可以进行密码解锁");
        System.out.println("解锁完毕,进入主界面");
        context.setState(AfterBootState.class);
        context.setScreenOn(true);
    }
    @Override void onPowerClick() {
        if(context.isScreenOn()) {
            System.out.println("熄屏");
        } else {
            System.out.println("亮屏,等待密码解锁");
        }
        context.setScreenOn(!context.isScreenOn());
    }
    @Override void onVolumeAscClick() { System.out.println("音量+"); }
    @Override void onVolumeDescClick() {  System.out.println("音量-"); }
}
// 具体状态 → 非第一次启动状态
public class NotFirstBootState extends State {
    @Override public void onHomeClick() {
        System.out.println("非首次启动,可以通过密码或指纹解锁");
        System.out.println("解锁完毕,进入主界面");
        context.setScreenOn(true);
        context.setState(AfterBootState.class);
    }
    @Override void onPowerClick() {
        if(context.isScreenOn()) {
            System.out.println("熄屏");
        } else {
            System.out.println("亮屏,等待密码或指纹解锁");
            context.setState(NotFirstBootState.class);
        }
        context.setScreenOn(!context.isScreenOn());
    }
    @Override void onVolumeAscClick() { System.out.println("音量+"); }
    @Override void onVolumeDescClick() {  System.out.println("音量-"); }
}
// 具体状态 → 启动后
public class AfterBootState extends State {
    @Override void onHomeClick() { System.out.println("返回主界面"); }
    @Override void onPowerClick() {
        if(context.isScreenOn()) {
            System.out.println("熄屏");
            context.setState(NotFirstBootState.class);
        } else {
            System.out.println("亮屏,等待密码或指纹解锁");
            context.getState().onHomeClick();
        }
        context.setScreenOn(!context.isScreenOn());
    }
    @Override void onVolumeAscClick() { System.out.println("音量+"); }
    @Override void onVolumeDescClick() {  System.out.println("音量-"); }
}
// 上下文信息类
public class StateContext {
    private boolean isScreenOn = false;   // 屏幕是否亮着
    public final static Map<Class, State> stateMap = new HashMap<>();
    private State state;    // 手机当前状态
    static {
        stateMap.put(CloseState.class, new CloseState());
        stateMap.put(FirstBootState.class, new FirstBootState());
        stateMap.put(NotFirstBootState.class, new NotFirstBootState());
        stateMap.put(AfterBootState.class, new AfterBootState());
    }
    public void setState(Class stateClass) {
        this.state = stateMap.get(stateClass);
        this.state.setContext(this);
    }
    public State getState() { return state; }
    public boolean isScreenOn() { return isScreenOn; }
    public void setScreenOn(boolean screenOn) {
        isScreenOn = screenOn;
        System.out.println("===> 屏幕处于:" + (isScreenOn ? "亮屏状态": "熄屏状态"));
    }
}
// 测试用例
public class StateTest {
    public static void main(String[] args) {
        StateContext context = new StateContext();
        context.setState(CloseState.class);
        // 处于关机状态点击音量- 和 home键
        context.getState().onVolumeDescClick();
        context.getState().onHomeClick();
        // 处于关机状态点击电源键
        context.getState().onPowerClick();
        context.getState().onPowerClick();
        context.getState().onHomeClick();
        context.getState().onVolumeAscClick();
    }
}


相关文章
|
2月前
|
设计模式 Java 测试技术
Java设计模式-状态模式(18)
Java设计模式-状态模式(18)
|
3月前
|
设计模式 网络协议 Java
【十五】设计模式~~~行为型模式~~~状态模式(Java)
文章详细介绍了状态模式(State Pattern),这是一种对象行为型模式,用于处理对象在其内部状态改变时的行为变化。文中通过案例分析,如银行账户状态管理和屏幕放大镜工具,展示了状态模式的应用场景和设计方法。文章阐述了状态模式的动机、定义、结构、优点、缺点以及适用情况,并提供了Java代码实现和测试结果。状态模式通过将对象的状态和行为封装在独立的状态类中,提高了系统的可扩展性和可维护性。
【十五】设计模式~~~行为型模式~~~状态模式(Java)
|
4月前
|
设计模式 JavaScript Go
js设计模式【详解】—— 状态模式
js设计模式【详解】—— 状态模式
80 7
|
5月前
|
设计模式 算法
行为型设计模式之模板模式
行为型设计模式之模板模式
|
5月前
|
设计模式
状态模式-大话设计模式
状态模式-大话设计模式
|
5月前
|
设计模式 存储
行为设计模式之状态模式
行为设计模式之状态模式
|
5月前
|
设计模式 存储
行为型设计模式之观察者模式
行为型设计模式之观察者模式
|
5月前
|
设计模式 算法
行为型设计模式
行为型设计模式
|
6月前
|
设计模式 存储 SQL
第四篇 行为型设计模式 - 灵活定义对象间交互
第四篇 行为型设计模式 - 灵活定义对象间交互
127 0
|
6月前
|
设计模式 算法 Java
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式