设计模式-状态模式

故事扮演 提交于 2019-12-16 07:19:52

状态模式

  • 定义

状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它所属的类,属于行为型模式

  • 状态模式类图
    在这里插入图片描述
  1. 环境(Context)角色,也成上下文:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
  2. 抽象状态(State)角色:定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。
  3. 具体状态(ConcreteState)角色:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。
  • 状态模式例子
    我们通常购物的时候,我们会先下订单,这个时候订单的状态就是待付款状态,这个时候我们可以去付款,付完款了,订单的状态就是待发货状态,这个时候订单可以去发货,商家发货了,这个时候订单的状态就是运送中,这个时候我们可以去收货,当我们确认收货了,订单的状态变成待评价状态,这个时候我们可以去评价订单,现在我们来用状态模式完成这个流程

先定义状态接口,里面有几个方法

public interface OrderState {

    // 付款
    public void pay();

    // 发货
    public void deliver();

    // 收货
    public void takeDeliver();

    // 评价
    public void appraise();
}

//////////////类分割////////////////
public class AbstractOrderState implements OrderState {
    protected Order order;

    public AbstractOrderState(Order order) {
        this.order = order;
    }

    @Override
    public void pay() {
        throw new RuntimeException("方法未定义");
    }

    @Override
    public void deliver() {
        throw new RuntimeException("方法未定义");
    }

    @Override
    public void takeDeliver() {
        throw new RuntimeException("方法未定义");
    }

    @Override
    public void appraise() {
        throw new RuntimeException("方法未定义");
    }
}

具体的状态类
待付款状态

public class ObligationState extends  AbstractOrderState{
    public ObligationState(Order order) {
        super(order);
    }

    @Override
    public void pay() {
        System.out.println("用户付款了");
        // 把订单的状态变成待发货状态
        order.setCurrentState(Order.deliverState);
    }
}

待发货状态

public class DeliverState extends AbstractOrderState {
    public DeliverState(Order order) {
        super(order);
    }

    @Override
    public void deliver() {
        System.out.println("订单已发货");
        order.setCurrentState(Order.shipState);
    }
}

运送中状态

public class ShipState extends AbstractOrderState {
    public ShipState(Order order) {

        super(order);
    }

    @Override
    public void takeDeliver() {
        System.out.println("用户确认收货");
        order.setCurrentState(Order.receivedState);
    }
}

已收货状态

public class ReceivedState extends AbstractOrderState {
    public ReceivedState(Order order) {
        super(order);
    }

    @Override
    public void appraise() {
        System.out.println("用户已评价");
    }
}

订单类

public class Order {

    public static OrderState obligationState;
    public static OrderState deliverState;
    public static OrderState receivedState;
    public static OrderState shipState;

    public Order() {
        obligationState = new ObligationState(this);
        deliverState = new DeliverState(this);
        receivedState = new ReceivedState(this);
        shipState = new ShipState(this);
    }

    private OrderState currentState;

    public OrderState getCurrentState() {
        return currentState;
    }

    public void setCurrentState(OrderState currentState) {
        this.currentState = currentState;
    }

    public void handle() {
        setCurrentState(Order.obligationState);
        currentState.pay();
        currentState.deliver();
        currentState.takeDeliver();
        currentState.appraise();
    }
}

测试

public class MyClient {

    public static void main(String[] args) {
        Order order = new Order();

        order.handle();
    }
}

运行结果

用户付款了
订单已发货
用户确认收货
用户已评价

状态和行为
  所谓对象的状态,通常指的就是对象实例的属性的值;而行为指的就是对象的功能,再具体点说,行为大多可以对应到方法上。

状态模式的功能就是分离状态的行为,通过维护状态的变化,来调用不同状态对应的不同功能。也就是说,状态和行为是相关联的,它们的关系可以描述为:状态决定行为 。

由于状态是在运行期被改变的,因此行为也会在运行期根据状态的改变而改变。

  • 总结
  1. 在状态模式中,环境(Context)是持有状态的对象,但是环境(Context)自身并不处理跟状态相关的行为,而是把处理状态的功能委托给了状态对应的状态处理类来处理。
  2. 在具体的状态处理类中经常需要获取环境(Context)自身的数据,甚至在必要的时候会回调环境(Context)的方法,因此,通常将环境(Context)自身当作一个参数传递给具体的状态处理类
  3. 客户端一般只和环境(Context)交互。客户端可以用状态对象来配置一个环境(Context),一旦配置完毕,就不再需要和状态对象打交道了。客户端通常不负责运行期间状态的维护,也不负责决定后续到底使用哪一个具体的状态处理对象。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!