leftso 82 2 2019-09-17 09:00:35

文章位置:左搜> 编程技术> Java编程技术> 正文

介绍

在本教程中,我们将探索另一种流行的行为设计模式 - 状态设计模式。

当我们处理可能存在于多个状态的对象时,状态设计模式的知识就派上用场了。 我们应该主要在对象的行为取决于其当前状态时使用它。 此模式有助于我们避免在该类的方法中对对象状态进行长时间条件检查。

有了它,让我们开始吧!
 

状态设计模式

我们可以使用以下UML图来表示状态设计模式:
状态设计模式
  • State  - 表示一个抽象类或接口,用于声明每个具体状态对象的最小预期功能
  • ConcreteState  - 这些是State的实现类
  • Context  - 这是我们向世界公开的类,通常负责维护当前的状态实例。 它还将责任委派给具体的状态类来执行任务

实战实例

假设我们有一台自动皂液器。 它理想地可以存在于这些状态 - 理想,分配或OutOfStock。 让我们借助状态图可视化它:

123

定义状态类

我们首先定义DispenserState接口:
public DispenserState {
 
    void sensesHand(AutoDispenser autoDispenser);
    void stopsSensingHand(AutoDispenser autoDispenser);
}
我们的每个状态类都必须实现DispenserState并定义该状态的行为。 我们的IdleState类看起来像:
public class IdleState implements DispenserState {
 
    public void sensesHand(AutoDispenser autoDispenser) {
        System.out.println("Hand sensed");
        autoDispenser.startDispensing();
        autoDispenser.setDispenserState(autoDispenser.getDispensingState());
    }
 
    public void stopsSensingHand(AutoDispenser autoDispenser) {
        System.out.println("Sensor inactive already!");
    }
}
同样,我们可以定义另外两个表示状态的类:
public class DispensingState implements DispenserState {
 
    public void sensesHand(AutoDispenser autoDispenser) {
        System.out.println("Already dispensing");
    }
 
    public void stopsSensingHand(AutoDispenser autoDispenser) {
        System.out.println("Stopped sensing");
        autoDispenser.stopDispensing(); 
        if(autoDispenser.getQuantity() > 1) {
          autoDispenser.setDispenserState(autoDispenser.getIdleState());
        } else {
          autoDispenser.setDispenserState(autoDispenser.getOutOfStockState());
        }
    }
}
 
public class OutOfStockState implements DispenserState {
 
    public void sensesHand(AutoDispenser autoDispenser) {
        System.out.println("nothing to dispense");
    }
 
    public void stopsSensingHand(AutoDispenser soapDispenser) {
        System.out.println("dispenser is already inactive");
    }
}

定义Context

最后,让我们定义我们的上下文类 -  AutoDispenser,它将与客户端代码进行交互:
public class AutoDispenser {
 
    private IdleState idleState;
    private DispensingState dispensingState;
    private OutOfStockState outOfStockState;
 
    private DispenserState currentDispenserState;
 
    public AutoDispenser() {
        this.idleState = new IdleState();
        this.dispensingState = new DispensingState();
        this.outOfStockState = new OutOfStockState();
        if(getQuantity() > 0) {
            this.currentDispenserState = idleState;
        } else {
             this.currentDispenserState = outOfStockState;
        }
    }
 
    public int getQuantity() {
        //returns current soap quantity
        ...
    }
 
    public void startDispensing() { ... }
 
    public void stopDispensing() { ... }
 
    public void sensesHand() {
        this.currentDispenserState.sensesHand(this);
    }
 
    public void stopsSensingHand() {
        this.currentDispenserState.stopsSensingHand(this);
    }
 
}
在这里,我们维护自动分配器的当前状态,并在具体的状态类中调用该方法来实现操作。
 

为何使用状态模式

除了帮助我们避免长期条件,它还提供其他好处:
  • 添加新状态非常简单直接,因为我们只需要定义另一个具体的状态类
  • 同样,删除状态只需要删除关联的类
  • 使代码更易于阅读和遵循
  • 是单一责任原则的一个很好的证明