设计模式-状态机模式

定义

状态模式也称为状态机模式,时允许对象在内部发生改变时改变它的行为。
状态模式将类的状态与行为进行绑定,类的行为是由状态决定的,不同状态下有不同的行为,意图让一个对象其内部状态改变时,它的行为也发生变化

结构

在这里插入图片描述
如上图,状态模式包含下面几个角色

  • 抽象状态角色
    定义该状态下的行为,行为可以是一个或多个
  • 具体状态角色
    具体实现该状态对应的行为,在必要时,需要进行状态切换
  • 环境类角色
    顶一个客户端需要的接口,内部维护一个当前状态的实例,并提供状态切换的入口。代码如下:
package com.lchtest.pattern.statemachine.general.simple;
// 抽象状态
public interface IState {
    void handle();
}
package com.lchtest.pattern.statemachine.general.simple;

public class ConcreteStateA implements IState{
    @Override
    public void handle() {
        System.out.println("StateA do action");
    }
}

package com.lchtest.pattern.statemachine.general.simple;

public class ConcreteStateB implements IState{
    @Override
    public void handle() {

        System.out.println("StateB do action");
    }
}
package com.lchtest.pattern.statemachine.general.simple;

public class Context {
    private static final IState STATE_A = new ConcreteStateA();
    private static final IState STATE_B = new ConcreteStateB();
    // 设置默认状态
    private IState currentState = STATE_A;
    // 用户切换状态
    public void setState(IState state){
        System.out.println("用户切换状态");
        this.currentState = state;
    }
    public void handle(){
        this.currentState.handle();
    }
}
package com.lchtest.pattern.statemachine.general.simple;

public class Test {
    public static void main(String[] args) {
        Context context = new Context();
        // 使用默认状态
        context.handle();
        // 切换状态为ConcreteStateB
        context.setState(new ConcreteStateB());
        context.handle();
    }
}

输出

StateA do action
用户切换状态
StateB do action

使用场景

当控制一个对象的状态的表达式过于复杂时,通常把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的逻辑简单化。对象的行为依赖于它的状态(属性),状态的改变会引起行为的改变。因此状态模式适用于下面场景:

  1. 行为跟随状态变化而改变的场景,如电商系统订单状态流转,工作流等
  2. 一个操作中含有庞大的多分支机构,具体执行哪个分支取决于对象的状态

代码示例

用一个论坛发表评论,收藏的例子来说明,用户登录后,可以直接评论,收藏文章,未登录时,跳转到登陆页面进行登录后才能进行评论,收藏操作:这里登录状态对应的行为是收藏,评论,未登录状态对应的行为是登录
创建抽象状态角色类:

package com.lchtest.pattern.statemachine.discuz;

/**
 * 抽象状态
 */
public abstract class UserState {
    // 上下文,子类需要引用
    protected AppContext appContext;

    public void setAppContext(AppContext appContext) {
        this.appContext = appContext;
    }

    // 状态下的行为
    public abstract  void favourite();
    public abstract  void comment(String comment);
}

创建登录状态类:

package com.lchtest.pattern.statemachine.discuz;

/**
 * 具体状态1- 登陆状态
 */
public class LoginState extends UserState {
    @Override
    public void favourite() {
        System.out.println("收藏成功");
    }

    @Override
    public void comment(String comment) {
        System.out.println("评论成功:" + comment);
    }
}

未登录状态

package com.lchtest.pattern.statemachine.discuz;

/**
 * 具体状态2- 未登陆状态
 */
public class UnLoginState extends UserState {
    @Override
    public void favourite() {
        this.switchToLogin();
        this.appContext.getState().favourite();
    }

    @Override
    public void comment(String comment) {
        this.appContext.getState().comment(comment);
    }

    // 用户切换状态
    private void switchToLogin(){
        System.out.println("切换状态,跳转到登陆页面");
        // 切换状态
        this.appContext.setState(this.appContext.SATE_LOGIN);
    }
}

上下文角色:

package com.lchtest.pattern.statemachine.discuz;

public class AppContext {

    public static final UserState SATE_LOGIN = new LoginState();
    public static final UserState SATE_UNLOGIN = new UnLoginState();
    // 设置默认状态
    private UserState currentState = SATE_UNLOGIN;

    {
        SATE_LOGIN.setAppContext(this); // 初始化状态
        SATE_UNLOGIN.setAppContext(this);
    }

    // 提供用户切换状态的方法
    public void setState(UserState state) {
        this.currentState = state;
    }

    // 提供用户获取当前状态的方法
    public UserState getState() {
        return this.currentState;
    }

    // 用户操作入口;状态的流转是系统内部决定的,而不是用户可以操作的!
    public void favourate() {
        this.currentState.favourite();

    }

    public void comment(String comment) {
        this.currentState.comment(comment);
    }
}

测试

package com.lchtest.pattern.statemachine.discuz;

public class Test {
    public static void main(String[] args) {
        AppContext  context = new AppContext();
        context.favourate();
        context.comment("评论:良心文章");
    }
}

在这里插入图片描述

状态机模式案例链接:
【设计模式】学习笔记14:状态模式(State)

设计模式:一目了然的状态机图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值