设计模式之状态模式-消灭switch,case(State)

问题

电脑城开始不满足于仅仅销售数码产品,着手研发产品。前期的话,先研发一些比较简单的产品,分别是台灯和电视。台灯的设计:在关闭状态下,点击开关按钮,从弱光—>强光—>关闭。电视的遥控器设计,在关闭状态下,点击开关按钮,打开电视,点击其他按钮,显示红灯,提示未开机。在开机状态下,点击开关按钮,关机,点击其他按钮,执行对应操作。如果不做任何考虑的话,可以在点击按钮时,判断当前状态,根据状态的不同来决定执行对应的操作。我们先来看看状态模式如何解决上述问题,再来看看其优劣。

实现

先看台灯的实现

public class TableLamp {

    private LampState lampState;

    public void onClick() {
        this.lampState.click(this);
    }

    public TableLamp() {
        lampState = new LampOffState();
    }

    public void setLampState(LampState lampState) {
        this.lampState = lampState;
    }
}

台灯的状态定义

public abstract class LampState {

    /**
     * 台灯开关点击事件
     */
    public abstract void click(TableLamp tableLamp);
}

public class LampOffState extends LampState {

    @Override
    public void click(TableLamp tableLamp) {
        System.out.println("from off to weak");
        tableLamp.setLampState(new LampWeakState());
    }
}

public class LampStrongState extends LampState {
    @Override
    public void click(TableLamp tableLamp) {
        System.out.println("from strong to off");
        tableLamp.setLampState(new LampOffState());
    }
}

public class LampWeakState extends LampState {

    @Override
    public void click(TableLamp tableLamp) {
        System.out.println("from weak to strong");
        tableLamp.setLampState(new LampStrongState());
    }
}

再来看电视遥控器

public class TvController {

    private TvState tvState;

    public TvController() {
        tvState = new OffState();
    }

    public void setTvState(TvState tvState) {
        this.tvState = tvState;
    }

    public  void nextChannel() {
        this.tvState.nextChannel();
    }
    public  void preChannel() {
        this.tvState.preChannel();
    }

    public  void turnUp() {
        this.tvState.turnUp();
    }

    public  void turnDown() {
        this.tvState.turnDown();
    }
}

电视的状态定义

public abstract class TvState {

    public abstract void nextChannel();

    public abstract void preChannel();

    public abstract void turnUp();

    public abstract void turnDown();
}

public class OffState extends TvState {

    public OffState() {
        System.out.println("关机");
    }

    @Override
    public void nextChannel() {
        System.out.println("关机状态,红灯闪烁提示");
    }

    @Override
    public void preChannel() {
        System.out.println("关机状态,红灯闪烁提示");
    }

    @Override
    public void turnUp() {
        System.out.println("关机状态,红灯闪烁提示");
    }

    @Override
    public void turnDown() {
        System.out.println("关机状态,红灯闪烁提示");
    }
}

public class OnState extends TvState{

    public OnState() {
        System.out.println("开机");
    }

    @Override
    public void nextChannel() {
        System.out.println("开机状态,下一频道");
    }

    @Override
    public void preChannel() {
        System.out.println("开机状态,上一频道");
    }

    @Override
    public void turnUp() {
        System.out.println("开机状态,调大音量");
    }

    @Override
    public void turnDown() {
        System.out.println("开机状态,调低音量");
    }
}

执行代码

        TableLamp tableLamp = new TableLamp();
        tableLamp.onClick();
        tableLamp.onClick();
        tableLamp.onClick();

        TvController controller = new TvController();
        controller.nextChannel();
        controller.preChannel();
        controller.turnDown();
        controller.turnUp();

        //开机
        controller.setTvState(new OnState());
        controller.nextChannel();
        controller.preChannel();
        controller.turnDown();
        controller.turnUp();

执行结果

from off to weak
from weak to strong
from strong to off

关机
关机状态,红灯闪烁提示
关机状态,红灯闪烁提示
关机状态,红灯闪烁提示
关机状态,红灯闪烁提示
开机
开机状态,下一频道
开机状态,上一频道
开机状态,调低音量
开机状态,调大音量

简介

可以看出:台灯和遥控器的实现方式有些微的不同。我将其按照是否会切换状态进行了分类,台灯开关点击就是直接对状态的切换,而遥控器点击事件是不对状态直接切换,而是在不同状态下其他按钮不同的操作(当然遥控器也是可以通过开关按钮进行状态切换的,只是我为了区分,将其分开)。

状态切换更类似于有限状态机,通过不同的操作,发生状态的变化,可以清晰的开出状态的切换过程,从A状态由何种操作转移到B状态。

此外,状态切换下,不同按钮下的操作,若按照传统实现方式,在点击时,switch当前状态,在不同的case下执行不同的操作,而这显然不符合开闭原则,若增加状态的话,所有的原始代码都需要进行修改。现在的话,只需要增加一个状态类即可,并且可以清晰的看出当前状态下,所有按钮点击后执行的操作。

总结

状态模式的定义是在一个对象的状态变化时改变其行为,看上去像是改变了其自身所属的类一样。其适用场景:对于一个对象有较多的状态切换,并且在不同状态下对于该对象的众多操作也不一样时。优点:符合单一职责,开闭原则;消除了大量状态判断语句;缺点:在少量状态和操作的情况下,会显得过度设计。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值