设计模式之状态模式的理解运用

引语:
我们在编程的时候,有时会遇到一些情况,那就是对象的行为动作会由当时对象所处的状态来决定。例如,我们在微博上看到一篇文章,觉得还不错,于是想评论或者转发,但如果用户没有登录,这个时候就会先自动跳转到登录注册界面,如果已经登录,当然就可以直接评论或者转发了。这里我们可以看到,我们用户的行为是由当前是否登录这个状态来决定的,这就是典型的状态模式情景。

为什么要使用状态模式?
在刚刚上述的情境中,如果我们不用状态模式也是可以的,但这就势必会使用很多if–else–条件判断了,几乎每一个行为动作,你都要去判断一次,例如评论:
if(已经登录){
System.out.print(“评论成功!”)
}else(未登录){
跳到登录界面
}
………………..
当然还包括很多其他动作,例如转发、分享、打赏等等,都要重复判断状态才行,如果程序随着需求的改动或者功能逻辑的增加需要修改代码,那么你只要遗漏了一个判断,就会出问题。
而使用状态模式,可以很好地避免过多的if–else –分支,状态模式将每一个状态分支放入一个独立的类中,每一个状态对象都可以独立存在,程序根据不同的状态使用不同的状态对象来实现功能。

怎样使用状态模式?
下面是状态模式的UML图:
这里写图片描述

  • Context: 环境类,定义客户感兴趣的接口,维护一个State子类的实例,这个实例对应的是对象当前的状态。
  • State:抽象状态类或者状态接口,定义一个或者一组行为接口,表示该状态下的行为动作。
  • ConcreteStateA、ConcreteStateB: 具体状态类,实现State抽象类中定义的接口方法,从而达到不同状态下的不同行为。

简单示例
下面是一个电视机遥控器为例来演示状态模式的实现。首先电视机的状态有开关两个状态,然后有搜台、上一台、下一台等操作。在电视机关闭的时候,只有开机键是有效的,其他都无效果;在开机的状态下,除了开机键之外,其他的都有效果。我们知道用if–else–来解决这种问题有点显得有点繁琐,下面我们直接用状态模式实现。

/** 电视机状态接口*/
public interface TVState{
    public void nextChannel();
    public void prevChannel();
    public void trunUp();
    public void trunDown();
}

/** 关机状态下的具体实现动作类,此时只有开机是有效的*/
public class PowerOffsetState implements TVState{
    @override
    public void nextChannel(){
    }
    @override
    public void prevChannel(){
    }
    @override
    public void trunUp(){
    }
    @override
    public void trunDown(){
    }
}

/** 开机状态的实现*/
public class PowerOnState implements TVState{
    @override
    public void nextChannel(){
        System.out.println("跳转到下一个频道")
    }
    @override
    public void prevChannel(){
        System.out.println("跳转到上一个频道")
    }
    @override
    public void trunUp(){
        System.out.println("音量增加")
    }
    @override
    public void trunDown(){
        System.out.println("音量减少")
    }
}

/** 电视遥控器,类似于经典状态模式中的Context*/
public class TVController{
    TVState state;
    public void setState(TVState state){
        this.state = state;
    }
    public void powerOn(){
        setState(new PowerOnState());
        System.out.println("开机啦!");
    }
    public void powerOff(){
        setState(new PowerOffState());
        System.out.println("关机啦!");
    }

    public void nextChannel(){
        state.nextChannel();
    }
    public void prevChannel(){
        state.prevChannel();
    }
    public void turnUp(){
        state.turnUp();
    }
    public void trunDown(){
        state.trunDown();
    }
}

/** 下面是客户端的调用代码*/
public class Client{
    public void main(String[] args){
        TVController controller = new TVController();
        //设置开机状态
        controller.powerOn();
        //下一个频道
        controller.nextChannel();
        //音量增加
        controller.trunUp();
        //关电视机
        controller.powerOff();
        //上一个频道,此时已经不会有反映了
        controller.prevChannel();
    }
}
输出结果如下:
开机啦!
跳转到下一个频道
音量增加
关机啦!

总结:
在对象的行动取决于本身的状态时,可以适用于状态模式,免去了过多的if–else判断,这对于一些复杂的和繁琐的判断逻辑有很好的帮助。但是使用状态模式,势必会造成更多的接口和类,对于非常简单的状态判断,可以不使用。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值