设计模式实战状态模式:原理篇
Posted mo_weifeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式实战状态模式:原理篇相关的知识,希望对你有一定的参考价值。
前言
小明开发的应用,账号有登录和未登录状态,现在要求点击个人中心头像时,如果是登录状态时,跳转到个人资料界面,如果是未登录状态时,跳转到登录界面。
小明是这样写的:
public class AccountManager
public static final int STATE_UNLOGIN = 0;//未登录状态
public static final int STATE_LOGIN = 1;//已登录状态
private int currentState;//当前状态
public AccountManager()
/**
* 设置状态
*/
public void setCurrentState(int state)
this.currentState = state;
if (currentState == STATE_UNLOGIN)
System.out.println("设置为未登录状态");
else if (currentState == STATE_LOGIN)
System.out.println("设置为登录状态");
private void gotoLogin()
System.out.println("跳转到登录界面");
private void gotoPersonInfo()
System.out.println("跳转到个人中心界面");
/**
* 点击头像的操作
*/
public void onClickHeadPortrait()
System.out.println("点击头像==>");
if (currentState == STATE_UNLOGIN)
gotoLogin();
else if (currentState == STATE_LOGIN)
gotoPersonInfo();
开始测试
public void test()
AccountManager accountManager = new AccountManager();
//登录
accountManager.setCurrentState(AccountManager.STATE_LOGIN);
accountManager.onClickHeadPortrait();
//退出登录
accountManager.setCurrentState(AccountManager.STATE_UNLOGIN);
accountManager.onClickHeadPortrait();
输出结果
设置为登录状态
点击头像==>
跳转到个人中心界面
设置为未登录状态
点击头像==>
跳转到登录界面
小明的领导一看,说这不是和上一次策略模式一样,如果要增加一个冻结状态、黑名单状态,分别要跳到解冻界面和申诉界面,岂不是要改动AccountManager类?AccountManager越来越复杂,充斥着各种if…else,违反开闭原则,扩展性很低。
领导建议这种因为不同状态,而导致不同结果的情景,可以使用状态模式代替。
使用状态模式改造
首先我们需要把状态抽象出来,将它标准化,做成抽象类。
public abstract class IAccountState
protected AccountContext context;
public AccountContext getContext()
return context;
public void setContext(AccountContext context)
this.context = context;
/**
* 点击头像
*/
public abstract void onClickHeadPortrait();
具体类继承抽象类
public class UnLoginState extends IAccountState
@Override
public void onClickHeadPortrait()
System.out.println("点击头像跳转到登录界面");
public class LoginState extends IAccountState
@Override
public void onClickHeadPortrait()
System.out.println("点击头像跳转到个人中心界面");
环境类
public class AccountContext
public static final IAccountState STATE_LOGIN = new LoginState();
public static final IAccountState STATE_UNLOGIN = new UnLoginState();
public static final IAccountState STATE_FROZEN = new FrozenState();
private IAccountState currentState = STATE_UNLOGIN;
public AccountContext()
STATE_LOGIN.setContext(this);
STATE_UNLOGIN.setContext(this);
STATE_FROZEN.setContext(this);
private void setCurrentState(IAccountState state)
this.currentState = state;
public IAccountState getCurrentState()
return currentState;
/**
* 登录成功
*/
public void loginSuccess()
setCurrentState(STATE_LOGIN);
/**
* 冻结账号
*/
public void frozen()
setCurrentState(STATE_FROZEN);
/**
* 退出登录
*/
public void exit()
setCurrentState(STATE_UNLOGIN);
/**
* 点击头像
*/
public void onClickHeadPortrait()
currentState.onClickHeadPortrait();
开始测试
public void test()
//初始化
AccountContext controller = new AccountContext();
//登录成功
controller.loginSuccess();
controller.onClickHeadPortrait();
//退出登录
controller.exit();
controller.onClickHeadPortrait();
输出结果
点击头像跳转到个人中心界面
点击头像跳转到登录界面
当我们想增加一个冻结状态时
public class FrozenState extends IAccountState
@Override
public void onClickHeadPortrait()
System.out.println("点击头像跳转到解冻界面");
public void test()
//初始化
AccountContext controller = new AccountContext();
//登录成功
controller.loginSuccess();
controller.onClickHeadPortrait();
//冻结账号
controller.frozen();
controller.onClickHeadPortrait();
//退出登录
controller.exit();
controller.onClickHeadPortrait();
点击头像跳转到个人中心界面
点击头像跳转到解冻界面
点击头像跳转到登录界面
状态模式讲解
看一下状态模式的UML图
State,抽象状态角色:抽象角色,通常使用接口或者抽象类实现。
ConcreteState,具体状态角色:实现了抽象角色的类,从而达到不同状态下的不同行为。
Context,环境角色,持有抽象角色的引用,给客户端调用。
意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
状态模式和策略模式
看下策略模式的UML图:
和状态模式一模一样,如何区分它们呢?
根据场景区分。策略是侧重算法的替换,状态是通过状态改变行为。
策略模式的使用场景:
- 诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
- 旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
- RecyclerView中的 LayoutManager。
状态模式的使用场景:
- 打篮球的时候运动员可以有正常状态、不正常状态和超常状态。
- 自动售卖机,有四个状态,分别是:没有硬币没有饮料、有硬币没有饮料、有硬币有饮料、没有硬币有饮料。有饮料时投币按按钮分派饮料(没有硬币有饮料<->有硬币有饮料),无饮料时投币按按钮返还硬币(没有饮料没有硬币<->有硬币没有饮料)。还有其他状态的行为,如在有硬币有饮料的时候,在投币,会拒绝,直接返还硬币等。
- 订单的各种状态,如待支付、未支付、支付中、支付失败
- 任务的各种状态,如待指派、待接受、待完成、已取消
- 在游戏系统中,人物有待机、走动、跳跃、释放技能中、死亡等状态,每个状态下的形态都会有所不同
在实际使用的时候,状态之间还有可能互相影响,比如订单在未支付时,点击支付,产品经理要求订单如果是从冻结状态变成待支付状态时,要把该订单放进一个风险列表进行风险监测,那你是不是还得知道该订单上一个状态是否冻结状态。而策略模式不会,策略和策略之间是单独存在的。
以上是关于设计模式实战状态模式:原理篇的主要内容,如果未能解决你的问题,请参考以下文章