最近在优化代码结构的时候无意间发现了状态模式,发现这个模式挺适合app内当需要判断用户是否登录执行不同操作的时候。下面会通过例子来说。
定义: 当一个对象的内部状态改变时允许改变其行为,这个对象看起来像是改变了其类。
适用性:
1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2.一个操作中含有大量与对象状态有关的条件语句,例如大量的(if-else、switch-case),且这些分支依赖于该对象的状态。 State模式将每一个条件分支放入一个独立的类中。 这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
下面直接以app中经常遇到的,当用户点赞或者收藏的时候需要判断用户是否登录的实例来说:
首先定义一个状态接口:
public interface UserState {
public void praise(Context context);
public void collect(Context context);
}
接口中定义了用户的点赞(praise)和收藏(collect)行为。
接着定义实现类LoginState、LogoutState:
public class LoginState implements UserState {
@Override
public void praise(Context context) {
System.out.print("praise");
}
@Override
public void collect(Context context) {
System.out.print("collect");
}
}
LoginState实现的是当用户登录的情况下所做的操作(点赞和收藏)。
public class LogoutState implements UserState {
@Override
public void praise(Context context) {
System.out.print("go to login");
}
@Override
public void collect(Context context) {
System.out.print("go to login");
}
}
LogoutState 实现的是当用户未登录的情况下所做的操作(跳转到登录页面)。
最后定义环境类LoginController
public class LoginController {
UserState userState = new LogoutState();
public static LoginController getInstance() {
return viewHolder.loginContext;
}
private static class viewHolder {
private static LoginController loginContext = new LoginController();
}
public void setUserState(UserState userState) {
this.userState = userState;
}
public void praise(Context context) {
userState.praise(context);
}
public void collect(Context context){
userState.collect(context);
}
}
LoginController定义了我们需要使用的接口,维护了一个UserState 子类的实例,这里默认是未登录。
接下来就是使用了:
public class MainActivity extends Activity {
@BindView(value = R.id.btn, click = "clickview")
private Button btn;
@BindView(value = R.id.btn1, click = "clickview1")
private Button btn1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Butterfly.bind(this);
}
public void clickview() {
LoginController.getInstance().setUserState(new LogoutState());
LoginController.getInstance().praise(this);
}
public void clickview1() {
LoginController.getInstance().setUserState(new LoginState());
LoginController.getInstance().collect(this);
}
}
上面就是一个简单的界面有两个按钮,分别模拟的登录和未登录状态;其中@BindView
和 Butterfly.bind(this);
用到了之前的一篇博客Android 学会写注解框架 里面的内容,有兴趣的可以看看,没有的可以直接换成正常的写法就好了。
上面代码用法比较简单,因为我的实现是把LoginController写成了单例模式,所以直接调用就行。
好了我了解的状态模式大致就是这样了,有不对的地方还望指出。