前言
状态模式中的行为是由状态来决定的,不同的状态下有不同的行为。
状态模式和策略模式的结构几乎完全一样,但他们的目的、本质却完全不一样。
状态模式的行为是平行的、不可替换的,而策略模式的行为是彼此独立、可互相替换的。
状态模式把对象的行为包装咋不同的状态对象里,每一个状态对象都有一个共同的抽象状态基类。
状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。
定义:
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
使用场景:
- 一个对象的行为取决于它的状态,并且它必须在运行时根据状态该改变它的行为;
- 代码中包含大量与对象状态有关的条件语句,如一个操作中含有大量的多分支语句(if-else或switch-case),且这些分支依赖于该对象的状态;
UML类图:
乍一看,这和策略模式简直一样,我们还是通过示例来看下两者的区别;
实现示例
我们以微博用户状态来举例
,状态可以分为登录
与未登录
状态,登录状态下可以正常转发和评论,未登录状态下提示去登录,如果不使用状态模式,则需要通过if-else判断状态处理,下面我们使用状态模式
来实现:
- 首先,定义用户登录状态接口,
UserState
interface UserState {
//评论
fun comment()
//转发
fun forward()
}
- 定义登录状态处理,
LoginState
class LoginState : UserState{
override fun comment() {
println("评论微博!")
}
override fun forward() {
println("转发微博!")
}
}
- 定义未登录状态处理,
LogoutState
class LogoutState : UserState {
override fun comment() {
println("未登录,请先去登录!")
}
override fun forward() {
println("未登录,请先去登录!")
}
}
- 定义状态管理类,
StateContext
class StateContext : UserState {
/**
* 默认未登录状态
*/
private var userState: UserState = LogoutState()
fun setState(userState: UserState) {
this.userState = userState
}
override fun comment() {
userState.comment()
}
override fun forward() {
userState.forward()
}
}
- 调用测试
object Test {
@JvmStatic
fun main(args: Array<String>) {
val userStateContext = StateContext()
userStateContext.comment() //默认未登录,会打印"未登录,请先去登录"
userStateContext.setState(LoginState())//切换到登录状态
userStateContext.forward() // 打印 "转发微博!"
}
}
可以看出状态之间是平行的、不可替换的,但可以相互转换。
Android源码中的状态模式
- Android WIFI状态切换中的
StateMachine
类;
public class StateMachine {
...
private static class SmHandler extends Handler {
private HaltingState mHaltingState = new HaltingState();
private QuittingState mQuittingState = new QuittingState();
private StateMachine mSm;
//定义HaltingState
private class HaltingState extends State {
@Override
public boolean processMessage(Message msg) {
mSm.haltedProcessMessage(msg);
return true;
}
}
定义QuittingState
private class QuittingState extends State {
@Override
public boolean processMessage(Message msg) {
return NOT_HANDLED;
}
}
private final State processMsg(Message msg) {
StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
//调用state.processMessage进行处理
while (!curStateInfo.state.processMessage(msg)) {
}
}
}
private SmHandler(Looper looper, StateMachine sm) {
super(looper);
mSm = sm;
addState(mHaltingState, null);
addState(mQuittingState, null);
}
}
....
}
总结
状态模式的关键点在于不同的状态下对于同一行为有不同的响应,其实就是将判断语句用多态来实现的一个具体示例。
优点:
将所有与一个特定的状态相关的行为都放入一个状态对象中,提供了一个更好的方法来组织与特定状态相关的代码,避免代码膨胀的同时也保证了可扩展性与可维护性。
缺点:
随着状态的增加必然会增加类和对象的个数。
结语
如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )