参考:https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/state.html
https://www.cnblogs.com/java-my-life/archive/2012/06/08/2538146.html
https://www.cnblogs.com/haoerlv/p/7777789.html
一:基本原理
定义:(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
1、有一个对象,它是有状态的。
2、这个对象在状态不同的时候,行为不一样。
3、这些状态是可以切换的,而非毫无关系。
状态模式包含如下角色:
Context:它就是那个含有状态的对象,它可以处理一些请求,这些请求最终产生的响应会与状态相关。
State:状态接口,它定义了每一个状态的行为集合,这些行为会在Context中得以使用。
ConcreteState:具体状态,实现相关行为的具体状态类。
上代码
代码一
public interface State {
/**
* 状态对应的处理
*/
public void handle(String sampleParameter);
}
public class ConcreteStateA implements State {
@Override
public void handle(String sampleParameter) {
System.out.println("ConcreteStateA handle :" + sampleParameter);
}
}
public class ConcreteStateB implements State {
@Override
public void handle(String sampleParameter) {
System.out.println("ConcreteStateB handle :" + sampleParameter);
}
}
public class Context {
//持有一个State类型的对象实例
private State state;
public void setState(State state) {
this.state = state;
}
/**
* 用户感兴趣的接口方法
*/
public void request(String sampleParameter) {
//转调state来处理
state.handle(sampleParameter);
}
}
public class Client {
public static void main(String[] args){
//创建状态
State state = new ConcreteStateB();
//创建环境
Context context = new Context();
//将状态设置到环境中
context.setState(state);
//请求
context.request("test");
}
}
代码二
public interface RunState {
void run(Hero hero);
}
public class CommonState implements RunState{
public void run(Hero hero) {
//正常跑动则不打印内容,否则会刷屏
}
}
public class SpeedUpState implements RunState{
public void run(Hero hero) {
System.out.println("--------------加速跑动---------------");
try {
Thread.sleep(4000);//假设加速持续4秒
} catch (InterruptedException e) {}
hero.setState(Hero.COMMON);
System.out.println("------加速状态结束,变为正常状态------");
}
}
public class SpeedDownState implements RunState{
public void run(Hero hero) {
System.out.println("--------------减速跑动---------------");
try {
Thread.sleep(4000);//假设减速持续4秒
} catch (InterruptedException e) {}
hero.setState(Hero.COMMON);
System.out.println("------减速状态结束,变为正常状态------");
}
}
public class SwimState implements RunState{
public void run(Hero hero) {
System.out.println("--------------不能跑动---------------");
try {
Thread.sleep(2000);//假设眩晕持续2秒
} catch (InterruptedException e) {}
hero.setState(Hero.COMMON);
System.out.println("------眩晕状态结束,变为正常状态------");
}
}
public class Hero {
public static final RunState COMMON = new CommonState();//正常状态
public static final RunState SPEED_UP = new SpeedUpState();//加速状态
public static final RunState SPEED_DOWN = new SpeedDownState();//减速状态
public static final RunState SWIM = new SwimState();//眩晕状态
private RunState state = COMMON;//默认是正常状态
private Thread runThread;//跑动线程
//设置状态
public void setState(RunState state) {
this.state = state;
}
//停止跑动
public void stopRun() {
if (isRunning()) runThread.interrupt();
System.out.println("--------------停止跑动---------------");
}
//开始跑动
public void startRun() {
if (isRunning()) {
return;
}
final Hero hero = this;
runThread = new Thread(new Runnable() {
public void run() {
while (!runThread.isInterrupted()) {
state.run(hero);
}
}
});
System.out.println("--------------开始跑动---------------");
runThread.start();
}
private boolean isRunning(){
return runThread != null && !runThread.isInterrupted();
}
}
二:使用
登录功能设计
参考:https://www.cnblogs.com/vegetate/p/9997193.html
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
//转发按钮
findViewById(R.id.activity_main).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LoginContext.getLoginContext().forward(MainActivity.this);
}
});
//注销按钮
findViewById(R.id.activity_main).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LoginContext.getLoginContext().setState(new LogoutState());
}
});
}
}
public class LoginActivity extends Activity {
EditText user;
EditText pwd;
@Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
findViewById(R.id.activity_main).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
login();
finish();
}
});
}
private void login() {
String name = user.getText().toString();
String pwd1 = pwd.getText().toString();
//执行网络请求
//登录成功后修改为已登录状态
LoginContext.getLoginContext().setState(new LoginedState());
}
public class LoginContext {
UserState mState = new LogoutState();
static LoginContext sLoginContext = new LoginContext();
private LoginContext() {
}
public static LoginContext getLoginContext() {
return sLoginContext;
}
public void setState(UserState aState) {
this.mState = aState;
}
public void forward(Context context) {
mState.forward(context);
}
public void comment(Context context) {
mState.comment(context);
}
}
public interface UserState {
public void forward(Context context);
public void comment(Context context);
}
/******************************************
* 类名称:LoginedState
* 类描述:已登录状态
* @time: 2016/11/16 14:13
******************************************/
public class LoginedState implements UserState {
@Override
public void forward(Context context) {
Log.i("TAG", "转发");
}
@Override
public void comment(Context context) {
Log.i("TAG", "评论");
}
}
public class LogoutState implements UserState {
@Override
public void forward(Context context) {
goToLogin(context);
}
@Override
public void comment(Context context) {
goToLogin(context);
}
private void goToLogin(Context context) {
Intent intent = new Intent(context, LoginActivity.class);
context.startActivity(intent);
}
}
如果不使用状态模式,在任何调用这些功能时都要进行是否登录的判断,代码逻辑就变成If-else,如果再增加用户一个状态,还需要再支持对这个状态的判断,使得模块很脆弱,一单忘记某个用户状态进行判断,很容易引发用户权限问题,
State模式将所有与一个特定的状态相关的行为都放入一个状态对象中,它提供了一个更好的方法来组织与特定状态相关的代码,将繁琐的状态判断转换成结构清晰的状态类族,在避免代码膨胀的同时也保证了可扩展性与可维护性