设计模式之状态模式

定义

Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.(当一个对象内在状态改变时容许其改变行为,这个对象看起来像改变了其类。)app

UML类图

角色解释

  • Context,环境,封装各类状态的变化,而且向外部提供全部须要的接口,使得外部不用关注状态的变化,只须要关注抽象的行为,以及初始状态。
  • State,状态,抽象全部状态的行为,而且依赖Context,提供setContext方法。
  • ConcreateState,状态实现,总结下就是每一个状态只关注本身的行为实现,针对不属于本身的行为能够进行抛错。

代码示例

已开门状态和关门状态举例:ide

Context类:this

public class DoorContext {
    public static final DoorState OPEN_STATE = new OpenState();
    public static final DoorState CLOSE_STATE = new CloseState();
    /**
     * 当前状态
     */
    private DoorState currentState;

    /**
     * 得到当前状态
     */
    public DoorState getCurrentState() {
        return currentState;
    }

    public void setCurrentState(DoorState doorState) {
        doorState.setDoorContext(this);
        this.currentState = doorState;
    }

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

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

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

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

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

State抽象类:code

public abstract class DoorState {
    protected DoorContext doorContext;

    public void setDoorContext(DoorContext _Door_context) {
        this.doorContext = _Door_context;
    }

    public abstract void open();

    public abstract void close();

    public abstract void enter();

    public abstract void out();

    public abstract void knock();

}

关门状态实现类:对象

@Override
    public void open() {
        System.out.println("开门");
        //切换状态
        super.doorContext.setCurrentState(DoorContext.OPEN_STATE);
    }


    @Override
    public void close() {
        System.out.println("已关门");
    }


    @Override
    public void knock() {
        System.out.println("关着的门用力敲");
    }


    @Override
    public void enter() {
        throw new RuntimeException("门关了,进门失败");
    }

    @Override
    public void out() {
        throw new RuntimeException("门关了,出门失败");
    }

开门状态实现类:blog

public class OpenState extends DoorState {
    @Override
    public void enter() {
        System.out.println("进入");
    }

    @Override
    public void out() {
        System.out.println("出来");
    }

    @Override
    public void knock() {
        System.out.println("开着的门轻轻敲");
    }

    @Override
    public void open() {
        System.out.println("门已经开着了");
    }

    /**
     * 涉及到切换到其余状态
     */
    @Override
    public void close() {
        System.out.println("关门");
        super.doorContext.setCurrentState(DoorContext.CLOSE_STATE);
    }
}

场景类1:接口

public static void main(String[] args) {
        DoorContext doorContext = new DoorContext();
        //给个初始状态
        doorContext.setCurrentState(DoorContext.CLOSE_STATE);
        //敲门
        doorContext.knock();
        //开门
        doorContext.open();
        //进门
        doorContext.enter();
        //关门
        doorContext.close();
        //进门
        doorContext.open();
        //出门
        doorContext.out();
        //关门
        doorContext.close();
    }

观察场景类能够知道,当场景类调用的时候,根本不须要在乎状态,只须要关注须要实现的行为,而具体能不能实现行为,具体怎么实现这个行为,状态的流转,则被封装在了Context里。get

应用场景

  • 行为与状态有相互依赖的关系。 也就是说,行为受状态影响(状态会改变行为),而状态也受行为影响(行为会改变状态),状态模式就是将每一个状态抽出来,而后针对每一个行为进行实现,遇到切换状态的行为的时候将当前场景Context里面的状态切换就好了。而对于Context来讲,只须要将外部的调用转发个当前场景内部的状态去处理就好了。

优势

  • 屏蔽了状态切换,而且又拥有良好的健壮性,没有忽视行为受状态的影响,只是封装在了状态内部去去处理了。
  • 符合单一职责,若是不该用状态模式,那么状态和行为是耦合在一个类中,不符合单一职责原则。
  • 符合开闭原则,高层模块不关注具体状态实现,若是须要扩展状态,只须要在底层添加一个状态实现类就是了。