《Android源码设计模式》读书笔记 (8) 第8章 状态模式

前言

  • 状态模式跟策略模式跟相似,从他们两个UML类图中就可以看出.
  • 状态模式其实就是一个将if-else用多态来实例的一个具体示例.

定义

  • 定义:当一个对象的类在状态改变时允许改变其行为,这个对象看起来像是改变了其类.
  • 使用场景:
    1.一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为.
    2.代码中包含大量与状态有关的if-else语句,并且它必须是在运行时根据状态的改变改变它的行为.其实有点类似:自定义listview下拉刷新时,动态的去改变headview的图片和文字,其实也就是几个状态根据高度的切换
  • 作用:通过多态来去除过多的,重复的if-else等分支语句
  • 优点:状态模式将所有与一个特定的状态相关的行为都放入一个状态对象中,它提供了一个更好的方法来组织和特定状态相关的代码,将烦琐的状态判断转换成结构清晰的状态类族,在避免代码膨胀的同时也保证了可扩展性和可维护性.
  • 缺点:状态模式的使用必然会增加系统类和对象的个数.

UML类图

这里写图片描述

  • context:上下文,跟state一对多的关系
  • state: 抽象状态类或者状态接口,表示该状态下的行为
  • ConcreteSateA:具体状态类,实现state接口

实现步骤

  • 案例:这里是直接模拟书上提供的案例,模拟电视开关机下的状态操作
  • 接下来是我们的demo目录截图 :
    这里写图片描述
  • 我们先来看看,很容易就常规的写法,作为对比,常规的if-else操作,把电视遥控器的相关行为全部归纳到TvController这个类里面:
  • 如果是有新的需求需要在该类进行修改和维护,是不是很麻烦了,有可能会动到以前正常的代码,这是不是又违反了代码设计模式的开闭原则呢?
/**
 * 常规代码if-else实现遥控器功能
 * @author max
 *
 */
public class TvController {
    //开机状态
    private final static int POWER_ON = 1;
    //关机状态
    private final static int POWER_OFF = 2;
    //默认状态是关机
    private int mState = POWER_OFF;

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

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

    public void nextChannel(){ //开机状态下下一个频道
        if (mState == POWER_ON) {
            System.out.println("下一个频道");
        }else{
            System.out.println("没有开机");
        }
    }

    public void prevChannel(){ //开机状态下上一个频道
        if (mState == POWER_ON) {
            System.out.println("上一个频道");
        }else{
            System.out.println("没有开机");
        }
    }

    public void turnUp(){ //开机状态下,增大音量
        if (mState == POWER_ON) {
            System.out.println("调高音量");
        }else{
            System.out.println("没有开机");
        }
    }

    public void turnOff(){ //开机状态下,降低音量
        if (mState == POWER_ON) {
            System.out.println("降低音量");
        }else{
            System.out.println("没有开机");
        }
    }
}
  • 在让我们来看看状态模式的实现,虽然类很多,但是思路和清晰明了.对于后期的维护只需要在接口里面实现对应新的方法即可.这里我们来看看状态模式的具体实现步骤吧
  • TvState:遥控器的功能接口,新业务直接在这里新增方法
/**
 * 电视状态接口--定义电视操作的函数
 * @author max
 *  */
public interface TvState {
    public void nextChannel();
    public void prevChannel();
    public void turnUp();
    public void turnOff();
}
  • PowerController:电源操作接口,也就是开机和关机的两个状态,有新的状态在这里新增方法
/**
 * 电源操作接口--开机关机
 * @author max
 *  */
public interface PowerController {
    public void powerOn();
    public void powerOff();
}
  • PowerOnStatePowerOffState这两个类主要是实现对应状态下TvState的业务方法:这里不贴代码了,有兴趣的同学下源码来看吧
  • TvControllerInState:这个类主要实现PowerController这个接口的方法,并提供对外设定状态和相关业务的方法,有点类似于builder模式的builder类.这里贴代码给大家看下
/**
 * 状态模式来实现开关机
 * @author max
 *
 */
public class TvControllerInState implements PowerController {
    TvState mTvState;

    /**
     * 对外方法,设置状态
     * @param mTvState
     */
    public void setmTvState(TvState mTvState) {
        this.mTvState = mTvState;
    }

    @Override
    public void powerOn() {
        System.out.println("开机了");
    }

    @Override
    public void powerOff() {
        System.out.println("关机了");
    }

    /**
     * 定义跟TvState接口一样的方法,返回
     */
    public void nextChannel() {
        mTvState.nextChannel();
    }

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

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

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

}
  • 当然最后是我们在调用这两种写法的代码,其优缺点大家也就一目了然了:
/**
     * 状态模式实现
     */
    private void stateMethod() {
        TvControllerInState state = new TvControllerInState();
        state.powerOn();//设置状态
        state.nextChannel();//调用业务代码
        state.prevChannel();
        state.turnUp();
        state.turnOff();
    }

    /**
     * 原始if-else实现
     */
    private void initailMethod() {
        TvController controller = new TvController();
        //先开机
        controller.powerOn();
        //开机后,在去调频道,关音量等等
        controller.prevChannel();
        //如果要设定关机状态,又要来调关机代码
        controller.powerOff();
        //如果要开机又要来调开机的代码,是不是很麻烦呢?省略...
    }

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值