java设计模式之状态模式

状态模式的定义:

  状态模式也叫做状态机模式,运行对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类,属于行为型设计模式。算法

  状态模式中类的行为是由状态决定的,在不一样的状态下有不一样的行为。其意图是让一个对象在其内部改变的时候,行为也随之改变。设计模式

状态模式的核心是装态与行为绑定,不一样的状态对应不一样的行为。架构

状态模式的应用场景:

  • 行为随状态改变而改变的场景。
  • 一个操做中含有庞大的多分支结构,而且这些分支取决于对象的状态。

状态模式的UML类图:

  状态模式的UML类图就不画了,由于它和策略模式的UML类图基本一致,它们都包含三个角色,ide

其中环境类角色(Context)分别是负责切换策略和状态,抽象角色分别是定义不一样策略和不一样状态测试

的行为,具体角色分别是策略的具体实现和状态的具体实现,惟一的区别是状态模式在完成某个状态this

的行为以后还有可能会切换到其余状态。spa

使用状态模式实现登陆状态自由切换:

  当咱们浏览博客园的文章时,若是咱们以为文章很好,忍不住想评论、收藏。可是若是咱们处于未登陆的状态,就会自动跳转到登陆页面设计

这里涉及到的状态有两种登陆和未登陆,行为有评论和收藏。下面使用状态模式来实现这个逻辑,代码以下。code

首先建立抽象状态角色类,定义评论和收藏两个行为对象

public abstract class UserState {
    protected AppContext context;

    public void setContext(AppContext context) {
        this.context = context;
    }

    public abstract void favorite();

    public abstract void comment(String comment);
}

而后建立未登陆状态类,定义在未登陆状态下,两种行为的具体实现

public class UnLoginState extends UserState {

    @Override
    public void favorite() {
        this.switch2login();
        this.context.getState().favorite();
    }

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

    private void switch2login(){
        System.out.println("跳转到登陆页!");
        this.context.setState(this.context.STATE_LOGIN);
    }
}

建立登陆状态类,定义在登陆状态下,两种行为的具体实现

public class LoginState extends UserState {
    @Override
    public void favorite() {
        System.out.println("收藏成功!");
    }

    @Override
    public void comment(String comment) {
        System.out.println(comment);
    }
}

建立上下文角色类,根据登陆状态切换具体的行为

public class AppContext {

    public static final UserState STATE_LOGIN = new LoginState();
    public static final UserState STATE_UNLOGIN = new UnLoginState();

    private UserState currentState = STATE_UNLOGIN;

    {
        STATE_LOGIN.setContext(this);
        STATE_UNLOGIN.setContext(this);
    }

    public void setState(UserState state){
        this.currentState = state;
    }

    public UserState getState(){
        return this.currentState;
    }

    public void favorite(){
        this.currentState.favorite();
    }

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

最后编写客户端测试代码。

public class Test {
    public static void main(String[] args) {
        AppContext context = new AppContext();
        context.favorite();
        context.comment("评论:好文章,360个赞");
    }
}

状态模式和责任链模式的区别:

  • 状态模式和责任链模式都能消除if...else分支过多的问题。可是在某些状况下,状态模式中的状态能够理解为责任,那么这种状况下,两种模式均可以使用。
  • 从定义上来看,状态模式强调的是一个对象内在状态的改变,而责任链模式强调的是外部节点对象间的改变。
  • 从代码实现上来看,二者最大的区别就是状态模式的各个状态对象知道本身要进入的下一个状态对象,而责任链模式并不清楚其下一个节点处理对象,由于链式组装由客户端负责。

状态模式和策略模式的区别:

  状态模式和策略模式的UML类图架构几乎彻底同样,但二者的应用场景是不同的。策略模式的多种算法行为则其一都能知足,彼此之间是独立的,用户可自行更换策略算法;而

状态模式的各个状态之间存在相互关系,彼此之间必定的条件下存在自动切换的效果,而且用户没法指定状态,只能设置初始状态,由于状态是根据行为而改变的。

状态模式的优势:

  • 结构清晰:将状态独立为类,清楚了冗余的if...else或switch...case语句,使代码更加间接,提升了系统的可维护性。
  • 将状态转换现实化:一般对象内部都是使用数值类型来定义状态的,状态的切换经过赋值进行表现,不够直观;而使用状态类,当切换状态时,是以不一样的类进行表示的,转换目的更加明确。
  • 状态类职责明确且具有扩展性。

状态模式的缺点:

  • 类膨胀,若是一个类的状态过多,则会形成状态类过多。
  • 状态模式的结构和实现都较为复杂,若是使用不当,将致使程序结构和代码的混乱。
  • 状态模式对开闭原则的支持不太友好,若是新增了状态类,则须要修改负责切换到该类的状态类。并且修改某个状态的行为也要修改源码。
相关文章
相关标签/搜索