小白谈谈状态模式

概念

当一个对象内在状态改变时,允许其改变行为,这个对象看起来像是改变了其类。也就是说,状态模式把对象的状态转换封装起来,当状态发生改变时,引起了行为发生改变,从外部看像是对象对应的类发生改变。


实现

案例:我就举一个我们最熟悉的案例——手机,手机的状态有很多种,这次我就简化手机的状态,只拿出4种状态进行举例:通话状态、锁屏状态、联网状态、充电状态。
我们都知道,在通话状态下,我们可以接收其他的来电;当我们把手机放到耳边,手机会进行自动锁屏;如果通话到一半,我们还可以充着电(这个可行,但不太建议)。
在锁屏状态下,我们可以接收来电,还可以联网和锁屏。
在联网状态下,我们可以锁屏或者充电。
在充电状态下,我们可以进行锁屏,联网,还可以接收来电。
整理可得:
在这里插入图片描述
首先定义一个手机状态的抽象类:

/**
 * 定义一个用于表示手机状态的抽象类
 */
public abstract class PhoneState {

    //定义一个封装的状态对象
    public StateContext stateContext;

    //定义一个设置状态的方法
    public void setStateContext(StateContext stateContext){
        this.stateContext = stateContext;
    }

    //定义手机的操作:来电,锁屏,联网,充电

    //定义手机来电操作
    public abstract void call();

    //定义手机锁屏操作
    public abstract void lock();

    //定义手机联网操作
    public abstract void net();

    //定义手机充电操作
    public abstract void charging();
}

再定义一个环境角色,用于串联各个状态

/**
 * 定义一个环境角色,用于串联各个状态
 */
public class StateContext {

    //实例手机的所有状态
    public final static CallingState callingState = new CallingState();
    public final static LockState lockState = new LockState();
    public final static NetState netState = new NetState();
    public final static ChargingState chargingState = new ChargingState();

    //定义手机
    private PhoneState phoneState;

    //获取手机当前状态
    public PhoneState getPhoneState() {
        return phoneState;
    }

    //设置当前手机状态
    public void setPhoneState(PhoneState phoneState){
        this.phoneState = phoneState;

        //实现状态之间不同状态对象的跳转
        this.phoneState.setStateContext(this);
    }

    public void call(){
        this.phoneState.call();
    }

    public void lock(){
        this.phoneState.lock();
    }

    public void net(){
        this.phoneState.net();
    }

    public void charging(){
        this.phoneState.charging();
    }
}

把手机各个状态进行具体代码逻辑的实现:

/**
 * 定义通话时可执行的操作
 */
public class CallingState extends PhoneState {

    //通话时要实现的动作
    @Override
    public void call() {
        System.out.println("您的号码正在通话中");
    }

    //通话时进行锁屏
    @Override
    public void lock() {
        super.stateContext.setPhoneState(StateContext.lockState);
        super.stateContext.getPhoneState().lock();
    }

    //通话时,无法联网
    @Override
    public void net() {
        //do nothing
    }

    //通话时,充电操作
    @Override
    public void charging() {
        super.stateContext.setPhoneState(StateContext.chargingState);
        super.stateContext.getPhoneState().charging();
    }
}
/**
 * 定义锁屏时可执行的操作
 */
public class LockState extends PhoneState {

    //锁屏状态下,来电
    @Override
    public void call() {
        super.stateContext.setPhoneState(StateContext.callingState);
        super.stateContext.getPhoneState().call();
    }

    //锁屏要执行的操作
    @Override
    public void lock() {
        System.out.println("您的手机正在锁屏!");
    }

    //锁屏状态下联网操作
    @Override
    public void net() {
        super.stateContext.setPhoneState(StateContext.netState);
        super.stateContext.getPhoneState().net();
    }

    //锁屏状态下,充电操作
    @Override
    public void charging() {
        super.stateContext.setPhoneState(StateContext.chargingState);
        super.stateContext.getPhoneState().charging();
    }
}
/**
 * 定义联网时可执行的操作
 */
public class NetState extends PhoneState {

    //联网时打不了电话
    @Override
    public void call() {
        //do nothing
    }

    //联网时,可以锁屏
    @Override
    public void lock() {
        super.stateContext.setPhoneState(StateContext.lockState);
        super.stateContext.getPhoneState().lock();
    }

    //联网的具体操作
    @Override
    public void net() {
        System.out.println("您的手机联网成功.....");
    }

    //联网时,可以充电
    @Override
    public void charging() {
        super.stateContext.setPhoneState(StateContext.chargingState);
        super.stateContext.getPhoneState().charging();
    }
}
/**
 * 定义充电时可执行的操作
 */
public class ChargingState extends PhoneState {

    //充电时,可以来电
    @Override
    public void call() {
        super.stateContext.setPhoneState(StateContext.callingState);
        super.stateContext.getPhoneState().call();
    }

    //充电时,可以锁屏
    @Override
    public void lock() {
        super.stateContext.setPhoneState(StateContext.lockState);
        super.stateContext.getPhoneState().lock();
    }

    //充电时可以联网
    @Override
    public void net() {
        super.stateContext.setPhoneState(StateContext.netState);
        super.stateContext.getPhoneState().net();
    }

    //充电的具体操作
    @Override
    public void charging() {
        System.out.println("您的手机正在充电");
    }
}

用客户端进行测试,本次客户端只进行了一种状态的测试:

public class Client {

    public static void main(String[] args) {

        StateContext stateContext = new StateContext();

        //来电时
        stateContext.setPhoneState(StateContext.callingState);

        stateContext.call();
        stateContext.net();
        stateContext.charging();
        stateContext.net();
    }
}

实验结果:
在这里插入图片描述

优点:避免了使用过多的条件判断语句,使程序看起来更加简化,较好地体现了开闭原则,单一职责原则,封装了转换规则,客户端不需要知道状态的转换是如何实现的。

缺点:如果对象状态很多,需要实现的子类也会相应复杂


本文的代码:https://pan.baidu.com/s/1heOeGEEpqVzXywz9BysHGg
提取码:k9rf

发布了48 篇原创文章 · 获赞 0 · 访问量 653

猜你喜欢

转载自blog.csdn.net/weixin_44943485/article/details/105338581