状态模式学习笔记

简介

状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时更改其行为。这种模式通过将对象状态转移的责任分配给代表状态的对象来实现。

实例

假设我们正在设计一个自动售货机系统。该系统中的自动售货机有三种状态:待机状态、选购商品状态和支付状态。在待机状态下,自动售货机不允许用户选购商品。在选购商品状态下,自动售货机会显示商品列表,并等待用户选择要购买的商品。在支付状态下,自动售货机会显示所选商品的价格,并等待用户支付。

我们可以使用状态模式来实现该系统。首先,我们定义一个接口 VendingMachineState 表示自动售货机的状态:

javaCopy Code
public interface VendingMachineState { void selectItem(String item); void insertMoney(int amount); void dispense(); }

然后,我们定义三个具体状态类:IdleState(待机状态)、SelectItemState(选购商品状态)和 PaymentState(支付状态)。

javaCopy Code
public class IdleState implements VendingMachineState { @Override public void selectItem(String item) { // 不允许选择商品 System.out.println("Please insert money first."); } @Override public void insertMoney(int amount) { // 进入选购商品状态 System.out.println(amount + " yuan inserted."); vendingMachine.setState(new SelectItemState(vendingMachine)); } @Override public void dispense() { // 不允许发放商品 System.out.println("Please select item first."); } } public class SelectItemState implements VendingMachineState { @Override public void selectItem(String item) { // 选择商品后进入支付状态 System.out.println(item + " selected."); vendingMachine.setItem(item); vendingMachine.setState(new PaymentState(vendingMachine)); } @Override public void insertMoney(int amount) { // 已经在选购商品状态下,不需要再次插入钱币 System.out.println("You have already inserted money."); } @Override public void dispense() { // 不允许发放商品 System.out.println("Please pay first."); } } public class PaymentState implements VendingMachineState { @Override public void selectItem(String item) { // 已经在支付状态下,不允许更改选择的商品 System.out.println("You have already selected item: " + vendingMachine.getItem()); } @Override public void insertMoney(int amount) { int total = vendingMachine.getAmount() + amount; vendingMachine.setAmount(total); // 判断是否已经足够支付 if (total >= vendingMachine.getPrice()) { vendingMachine.setState(new DispensingState(vendingMachine)); } else { System.out.println("Current balance: " + total); } } @Override public void dispense() { // 不允许发放商品 System.out.println("Please insert enough money."); } } public class DispensingState implements VendingMachineState { @Override public void selectItem(String item) { // 已经在发放商品状态下,不允许更改选择的商品 System.out.println("You have already selected item: " + vendingMachine.getItem()); } @Override public void insertMoney(int amount) { // 已经足够支付,不需要继续插入钱币 System.out.println("You have already inserted enough money."); } @Override public void dispense() { // 发放商品并进入待机状态 System.out.println("Item " + vendingMachine.getItem() + " dispensed."); vendingMachine.setState(new IdleState(vendingMachine)); } }

最后,我们定义一个自动售货机类 VendingMachine 来管理自动售货机的状态:

javaCopy Code
public class VendingMachine { private String item; private int price; private int amount; private VendingMachineState state; public VendingMachine(String item, int price) { this.item = item; this.price = price; this.amount = 0; this.state = new IdleState(this); } public void selectItem(String item) { state.selectItem(item); } public void insertMoney(int amount) { state.insertMoney(amount); } public void dispense() { state.dispense(); } public String getItem() { return item; } public void setItem(String item) { this.item = item; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public int getAmount() { return amount; } public void setAmount(int amount) { this.amount = amount; } public void setState(VendingMachineState state) { this.state = state; } }

现在,我们可以使用自动售货机类 VendingMachine 来创建一个自动售货机实例,并进行测试:

javaCopy Code
VendingMachine vendingMachine = new VendingMachine("Coke", 5); // 初始状态为待机状态 vendingMachine.selectItem("Coke"); // 输出:Please insert money first. // 插入 2 元钱后进入选购商品状态 vendingMachine.insertMoney(2); // 输出:2 yuan inserted. vendingMachine.selectItem("Coke"); // 输出:Coke selected. // 插入 3 元钱后进入支付状态 vendingMachine.insertMoney(3); // 输出:Current balance: 5 vendingMachine.insertMoney(1); // 输出:Item Coke dispensed. // 发放商品后进入待机状态 vendingMachine.dispense(); // 输出:Please insert money first.

以上就是一个简单的自动售货机系统实例,使用了状态模式来实现不同状态之间的切换以及相应的行为。