设计模式:状态模式
一、定义
依据状态的不同,调用同样的方法却有不同的行为
二、角色
- Context:环境,定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
- State:抽象状态,定义一个接口以封装与Context的一个特定状态相关的行为。
- ConcreteState:每一子类实现一个与Context的一个状态相关的行为。
三、使用场景
- 一个对象的行为取决于它的状态,并且它必须在运行时根据状态该改变它的行为;
- 代码中包含大量与对象状态有关的条件语句,如一个操作中含有大量的多分支语句(if-else或switch-case),且这些分支依赖于该对象的状态;
四、使用案例
车辆限行
1.抽象出一个接口方法,判断是否限行
public interface Check {boolean limit(int lastNumber);
}
2.定义周一和周二两种不同状态同个limit方法下,不同的处理行为。
public class Monday implements Check {@Overridepublic boolean limit(int lastNumber) {if (lastNumber == 1 || lastNumber == 6) {return true;}return false;}
}public class Tuesday implements Check {@Overridepublic boolean limit(int lastNumber) {if (lastNumber == 2 || lastNumber == 7) {return true;}return false;}
}
3.定义一个判断限行的类,来统一管理和处理
public class LimitLine {private Check check;public void setCheck(Check check) {this.check = check;}public boolean getLimitLine (int lastNumber) {return check.limit(lastNumber);378915406@qq.com}
}
4.调用
Monday monday = new Monday();Tuesday tuesday = new Tuesday();LimitLine limitLine = new LimitLine();limitLine.setCheck(monday);boolean mondayLimitOne = limitLine.getLimitLine(1);boolean mondayLimitTwo = limitLine.getLimitLine(2);limitLine.setCheck(tuesday);boolean tuesdayLimitOne = limitLine.getLimitLine(1);boolean tuesdayLimitTwo = limitLine.getLimitLine(2);Log.d("State","mondayLimitOne = " + mondayLimitOne);Log.d("State","mondayLimitTwo = " + mondayLimitTwo);Log.d("State","tuesdayLimitOne = " + tuesdayLimitOne);Log.d("State","tuesdayLimitTwo = " + tuesdayLimitTwo);
五、在Android中的使用
WIFI管理模块。
当WIFI开启时,自动扫描周围的接入点,然后以列表的形式展示;当wifi关闭时则清空。这里wifi管理模块就是根据不同的状态执行不同的行为
六、优缺点
优点:
- 将所有与一个特定的状态相关的行为都放入一个状态对象中,提供了一个更好的方法来组织与特定状态相关的代码,避免代码膨胀的同时也保证了可扩展性与可维护性。
缺点:
- 随着状态的增加必然会增加类和对象的个数
七、和策略模式的区别:
- 状态模式是跟状态密切相关,同样的行为可能不同的状态会有不同的处理方式,状态是平行的。策略模式是根据策略分类,不同的策略,不同的算法会使用不同的策略,策略间是相互独立的。
- 对于Client 端两种模式是两种不同的存在方式
- 状态模式中不同的状态类在Client端并不需要出现,Client 只需要调用Context的接口就可以。
- 策略模式中不同的策略必须是在Client 端出现的,Client会根据不同的需要选择不同的策略,这一点Context 无法去控制。
- 两种模式Context 类控制方式不同
- 状态模式中不同的状态类不需要在Client 中出现,Client只需要操作接口,例如上面例子中电视的频道调节,Client 只需要调用nextChannel() 即可,所以Context 的构造函数可以将State 作为参数,也可以不将其作为参数传入。
- 策略模式中Client 必须要知道策略,所以Context的构造函数或者其他接口必须要将Stragety 作为参数传入。