概念:状态模式中的行为是由状态来决定的,不同的状态有不同的行为,状态模式把对象的行为包装在不同的状态对象里,每一个对象都有一个共同的抽象状态基类,状态模式的意图是让一个对象在他的内部状态改变的时候,其行为也随之改变。
常见使用场景:
微博的转发和评论,在登录状态和未登录状态执行的行为也是不一样的。
示例:
1、定义一个UserState接口,里面声明了所有行为的方法:
/**
* Created by jin.li on 2017/6/3.
* 表示用户的当前状态
*/
public interface UserState {
//转发
public void forward(Context context);
//评论
public void comment(Context context);
}
2、LoginState和LogouState实现了UserState
/**
* Created by jin.li on 2017/6/3.
*/
public class LoginState implements UserState {
@Override
public void forward(Context context) {
//转发
}
@Override
public void comment(Context context) {
//评论
}
}
/**
* Created by jin.li on 2017/6/3.
*/
public class LogouState implements UserState {
@Override
public void forward(Context context) {
//goto LoginActivity
}
@Override
public void comment(Context context) {
//goto LoginActivity
}
}
3、MainActivity完成了转发、评论及注销的功能:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_forward = (Button) findViewById(R.id.btn_forward);
Button btn_logout = (Button) findViewById(R.id.btn_logout);
//转发
btn_forward.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LoginContext.getLoginContext().forward(MainActivity.this);
}
});
//注销
btn_logout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//注销后,同步更新状态
LoginContext.getLoginContext().setState(new LogouState());
}
});
}
}
4、LoginActivity为地登录页面:
private EditText usernameEdit;
private EditText pwdEdit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
usernameEdit = (EditText) findViewById(R.id.username);
pwdEdit = (EditText) findViewById(R.id.pwd);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
login();
finish();
}
});
}
private void login() {
String username = usernameEdit.getText().toString().trim();
String pwd = pwdEdit.getText().toString().trim();
//修改状态为登录状态
LoginContext.getLoginContext().setState(new LoginState());
}
}
5、LoginContext,用户接口和状态管理类,通过setState来对状态进行改变,并且把操作委托给状态对象,不同的状态对象对于同一个操作进行不同的车处理。
public class LoginContext {
//默认为未登录状态
UserState mState = new LogouState();
public static LoginContext sLoginContext = new LoginContext();
public static LoginContext getLoginContext() {
return sLoginContext;
}
public void setState(UserState state) {
this.mState = state;
}
public void forward(Context context) {
mState.forward(context);
}
public void comment(Context context) {
mState.comment(context);
}
}
6、总结:
UserState中有两个方法:转发和评论,在已登录的状态下,执行转发和评论,反之进入登录页面,登录后更新状态为已登录状态。避免了大量的if else,即使用户增加了状态,代码结构也依然很清晰,反之,如果使用if else,那么每一个功能函数的if else都要全部重新修改,这样使得这个模块变得很脆弱。
参考:《Andorid源码设计模式解析与实战》