状态模式将状态封装成为独立的类,并将动作委托到代表当前状态的对象,将容易产生问题的if语句删除,以方便日后的维护,同时也让每一个状态对修改关闭,让含有状态的类对扩展开放。
状态模式
定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
UML图
- 内容:内部持有某些状态接口,并维护着对象的现有状态
- 状态接口:抽象状态类或者接口,用以封装行为
- 具体状态:具体状态类,实现了状态接口中的方法
例子
以登录场景为例,我们知道如果想发送微博或者在他人微博下方留言,那么服务器会检查我们是否已经登录,即是否符合这个状态,如果符合的话,则会进行后续的业务逻辑处理。
那我们通常会怎么做呢?
if(已经登录){
//发表微博
}else{
//请登录
}
if语句的处理会给日后代码的扩展造成不良的影响,不方便维护,一旦我们增加了新的一种状态,就需要增添新的if/else语句,在添加一项功能时,要对所有的状态进行判断,会造成代码的臃肿不堪,且一旦漏掉对某个状态的判断,那么就会出现BUG。状态模式则是解决这个问题的好手。
state接口
package state;
public interface State {
void validation();
}
state接口实现类
package state;
public class LoginState implements State {
Context context;
public LoginState(Context context) {
this.context = context;
}
@Override
public void validation() {
System.out.println("I'm loggin");
}
}
package state;
public class LogoutState implements State {
Context context;
public LogoutState(Context context) {
this.context = context;
}
@Override
public void validation() {
System.out.println("I'm loggout");
}
}
Context
package state;
public class LogInContext{
State mState = new LogOutState();//初始化为未登录状态
static LogInContext mLogInContext = new LogInContext();
private LogInContext(){}
//使用单例模式提供管理类实例
public static LogInContext getLogInContextInstance(){
return mLogInContext;
}
public void valadition(){
mState.valadition();
}
public void setState (State state){
this.mState = state;
}
}}
使用
//登录界面LogInActivity
if(登录验证成功){
LogInContext.getLogInContextInstance.setState(new LogInState());
finish();
}
//注销账户
LogInContext.getLogInContextInstance.setState(new LogOutState());
小结
状态模式的使用很好的避免了if/else语句给代码维护带来的问题,但是同时也会使得类和对象增多。
状态模式和策略模式是双胞胎,但是策略模式是使用算法族的组合来实现程序的解耦和可扩展性,而状态模式则依靠对象内部状态的行为来控制自身行为。前者的算法组是可以互相代替的,而后者的状态决定了行为,因此无法相互代替。
源码在这里:我的github地址
其他设计模式:设计模式学习笔记