java设计模式(十四)——状态模式

1、基本概念

状态模式( State Pattern )也称为状态机模式(State Machine Pattern) ,是允许对象在内
部状态发生改变时改变它的行为,对象看起来好像修改了它的类,属于行为型模式。

 

场景实例:订单的状态改变,工作流程的状态改变

 

2、类图和角色

类图:

 

 

 看起来和策略模式很像,抽象,具体,上下文三个对象

角色:

上下文context : 负责维护一个当前状态对象和具体实例状态的切换

抽象状态类:定义状态下的行为

具体状态类:具体状态下行为的实现,并进行状态的切换

 

3、案例

案例:一个app,用户评论一篇文章,如果用户没有登录,就让其跳转到登录页面进行登录,成功后,切换当前的状态位已登录用户

示意图:

 

 

 类图:

 

 

 

抽象状态:接口IUserStatus,定义一个统一的接口方法

public interface IUserStatus {

    void comment(String msg);

}

抽象状态:抽象类UserStatus

public abstract class UserStatus implements IUserStatus{

    protected Context context;

    public void setContext(Context context){
        this.context = context;
    }
    public abstract void comment(String msg);
}

具体抽象:登录状态类LoginStatus 

public class LoginStatus extends UserStatus {

    @Override
    public void comment(String msg) {
        System.out.println("登录用户xxx:"+msg);
    }
}

具体抽象:未登录状态类NoLoginStatus ,执行comment方法前,进行状态的切换

public class NoLoginStatus extends UserStatus {
    @Override
    public void comment(String msg) {
        //进行登录后才可评论
        System.out.println("系统信息:当前用户未登录,请前往登录");
        toLoginOn();
        this.context.getCurrentUserStatus().comment(msg);
    }

    public void toLoginOn() {
        //登录,修改状态
        this.context.setUserStatus(context.LOGIN_STATUS);
        System.out.println("系统信息:登录成功");
    }
}

上下文:Context ,负责状态的切换与获取

public class Context {
    public static final LoginStatus LOGIN_STATUS = new LoginStatus();
    public static final NoLoginStatus NO_LOGIN_STATUS =new NoLoginStatus();

    private UserStatus currentUserStatus = NO_LOGIN_STATUS;

    public Context(){
        LOGIN_STATUS.setContext(this);
        NO_LOGIN_STATUS.setContext(this);
    }

    public void setUserStatus(UserStatus userStatus){
        this.currentUserStatus = userStatus;
        this.currentUserStatus.setContext(this);
    }

    public UserStatus getCurrentUserStatus(){
        return this.currentUserStatus;
    }
}

 

测试:

public class Test {
    public static void main(String[] args) {
        Context context = new Context();
        UserStatus userStatus = new NoLoginStatus();
        userStatus.setContext(context);
        userStatus.comment("老铁,666");
    }
}

输出结果:

系统信息:当前用户未登录,请前往登录
系统信息:登录成功
登录用户xxx:老铁,666

4、优缺点

优点;

1、结构清晰,可以干掉if..else语句, 使代码更加简洁
2、状态类职责明确且具备扩展性。

缺点:不符合开闭原则,当我们需要新增一个管理员状态的对象,就需要在登陆的时候切换状态,

那么我们就需要修改context中的代码和LoginStatus的代码

posted @ 2020-07-21 22:45  来一杯可乐  阅读(622)  评论(0)    收藏  举报