概述
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
使用场景
行为随状态改变而改变的场景。
优点
- 封装了转换规则
- 方便添加新的状态
- 将状态转换的逻辑和状态对象合成一体,代替复杂的
if else
缺点
- 产生大量对象
- 结构复杂,转换逻辑不能一目了然
类图解析
环境Context 它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理。
抽象状态State(含有状态对应的方法)(开机,关机) 和对应的行为(开机按键,关机按键)定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。
具体状态 实现抽象状态定义的接口。
状态 决定 行为(比如登录之后才能做增删改查,不能登录就只能注册找回密码)
代码实现(以登录加载数据为例)
1.首先要抽象出状态State(interface)例子,这里只有登录,登出,加载数据几个行为(method).
public interface LoginState {
/**
*
*/
public void loadUser();
public void loginIn();
public void loginOut();
}
2.建立具体状态实现State中的行为状态:登录成功状态,退出登录状态,并且将状态对应的动作实现.
public class LoginInState implements LoginState{
@Override
public void loadUser() {
// TODO Auto-generated method stub
System.out.println("用户数据载入成功");
}
@Override
public void loginIn() {
// TODO Auto-generated method stub
System.out.println("已经登录成功了");
}
@Override
public void loginOut() {
// TODO Auto-generated method stub
System.out.println("已经登录成功了,请按退出登录按钮");
}
}
public class LoginErrorState implements LoginState{
@Override
public void loadUser() {
// TODO Auto-generated method stub
System.out.println("已经退出,请按登录按钮");
}
@Override
public void loginIn() {
// TODO Auto-generated method stub
System.out.println("已经退出,请先登录");
}
@Override
public void loginOut() {
// TODO Auto-generated method stub
System.out.println("退出登录成功");
}
}
3.用Context上下文,持有状态State的实现,统一对行为进行操作.将与状态相关的操作委托给当前的Concrete State对象来处理.
/**
* 登录环境上下文
* @author ccj
*
*/
public class LoginContext {
private LoginState loginState=new LoginErrorState();
/**
* 可以根据需求,进行单例化,工厂化
*/
public void loginIn(){
loginState=new LoginInState();
loginState.loginIn();
}
public void loginOut(){
loginState=new LoginErrorState();
loginState.loginOut();
}
public void loadUser(){
loginState.loadUser();
}
}
4.客户端测试按键动作
public class Test {
/**
* 将登录登出两个动作, 分别对应两个按钮
* @param args
*/
public static void main(String[] args) {
LoginContext context =new LoginContext();
System.out.println("=======点击登录按钮===>>=状态:登录=====>>选择加载用户数据===========");
context.loginIn();
context.loadUser();
System.out.println("=====点击退出按钮>>======状态:退出=======>>选择加载用户数据=========");
context.loginIn();
context.loginOut();
context.loadUser();
}
}
5.测试结果
=======点击登录按钮===>>=状态:登录=====>>选择加载用户数据===========
已经登录成功了
用户数据载入成功
=====点击退出按钮>>======状态:退出=======>>选择加载用户数据=========
已经登录成功了
退出登录成功
已经退出,请按登录按钮
总结
状态模式确实优雅,但是需要花时间理解 转换逻辑,状态和行为, 不如if else
简单粗暴...