状态设计模式

状态模式(State Pattern)是一种行为设计模式,它允许一个对象在其内部状态发生改变时改变其行为。这种模式的关键是将状态相关的行为分散到不同的状态对象中,通过状态对象的变化来改变上下文对象的行为。

下面是一个使用状态模式的缴费项目处理系统的简化示例:

缴费项目的需求:
1)有一个缴费项目包含缴费的信息,说明是何费用。
2)添加缴费的人员,可以以一个集体为单位。
3)缴费项目中有多哥缴费选项,缴费人员可以选择自己需要的内容进行缴费。
4)根据缴费人员选择的缴费选项生成一条合并的账单,并计算金额。
5)缴费项目分为四个状态:草稿、未开始、进行中、已关闭。只有草稿状态可以编辑缴费信息,选够项,已经生成账单。
在这里插入图片描述

核心类

  1. FeeItem: 表示一个具体的缴费项目。
  2. FeeOption: 表示一个缴费项目的具体选项。
  3. Person: 表示一个缴费人员。
  4. Bill: 表示每个人的账单,包括选择的缴费项和总金额。
  5. FeeManager: 管理所有的缴费项目、选项和账单生成。
  6. PaymentState: 管理缴费项目不同状态的行为。

设计与实现

1. FeeItem 类
import java.util.List;

public class FeeItem {
    private String name;
    private List<FeeOption> options;

    public FeeItem(String name, List<FeeOption> options) {
        this.name = name;
        this.options = options;
    }
}
2. FeeOption 类
public class FeeOption {
    private String description;
    private double amount;

    public FeeOption(String description, double amount) {
        this.description = description;
        this.amount = amount;
    }


}
3. Person 类
public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

}
4. Bill 类
import java.util.List;

public class Bill {
    private Person person;
    private List<FeeOption> selectedOptions;
    private double totalAmount;

    public Bill(Person person, List<FeeOption> selectedOptions) {
        this.person = person;
        this.selectedOptions = selectedOptions;
        this.totalAmount = calculateTotal();
    }

    private double calculateTotal() {
        return selectedOptions.stream().mapToDouble(FeeOption::getAmount).sum();
    }
}
5. FeeManager 类
/**
 * PaymentContext
 */
@Data
public class FeeManager {

    private PaymentState state;
    private FeeItem feeItem;
    private List<Bill> bills;

    public FeeManager() {
        this.feeItem = new FeeItem("2024淑妃");
        this.bills = new ArrayList<>();
        this.state = new DraftState();
    }


    /**
     *  添加选购项
     * @param name
     * @param amount
     */
    public void addFeeOption(String name, Long amount) {
        FeeOption feeOption = new FeeOption(name, amount);
        state.addFeeOption(this, feeOption);
    }

    public void generateBillForPerson(Person person, List<FeeOption> selectedOptions) {
        Bill bill = new Bill(person, selectedOptions);
        bills.add(bill);
    }

}

6. 状态接口
/**
 * 定义一个状态接口,声明所有状态需要实现的方法:
 */
public interface PaymentState {

    /**
     * 添加选购项
     *
     * @param context
     * @param option
     */
    void addFeeOption(FeeManager context, FeeOption option);
}


/**
 * 草稿状态
 */
class DraftState implements PaymentState {

    @Override
    public void addFeeOption(FeeManager context, FeeOption option) {
        System.out.println("目前是草稿状态,可以添加选购项!");
        List<FeeOption> options = context.getFeeItem().getOptions();
        if (options == null) {
            options = new ArrayList<>();
        }
        options.add(option);
        context.getFeeItem().setOptions(options);
    }


}

/**
 * 未开始
 */
class NotStartedState implements PaymentState {

    @Override
    public void addFeeOption(FeeManager context, FeeOption option) {
        System.out.println("目前是未开始状态,不可能添加修改项目");
    }


}

/**
 * 进行中
 */
class InProgressState implements PaymentState {


    @Override
    public void addFeeOption(FeeManager context, FeeOption option) {
        System.out.println("目前是进行中状态,不可能添加修改项目");
    }


}

/**
 * 已关闭
 */
class FailedState implements PaymentState {


    @Override
    public void addFeeOption(FeeManager context, FeeOption option) {
        System.out.println("目前是已关闭状态,不可能添加修改项目");
    }


}

示例使用

public static void main(String[] args) {
        FeeManager feeManager = new FeeManager();
        feeManager.addFeeOption("语文",222L);
        feeManager.setState(new FailedState());
        feeManager.addFeeOption("语文",222L);
        feeManager.setState(new InProgressState());
        feeManager.addFeeOption("语文",222L);
        feeManager.setState(new NotStartedState());
        feeManager.addFeeOption("语文",222L);
        System.out.println(feeManager.getFeeItem());
    }
上一篇:虚拟机Ubuntu扩展磁盘大小


下一篇:HTML开发 Vue2.x + Element-UI 动态生成表单项并添加表单校验