状态模式(State Pattern)是一种行为设计模式,它允许一个对象在其内部状态发生改变时改变其行为。这种模式的关键是将状态相关的行为分散到不同的状态对象中,通过状态对象的变化来改变上下文对象的行为。
下面是一个使用状态模式的缴费项目处理系统的简化示例:
缴费项目的需求:
1)有一个缴费项目包含缴费的信息,说明是何费用。
2)添加缴费的人员,可以以一个集体为单位。
3)缴费项目中有多哥缴费选项,缴费人员可以选择自己需要的内容进行缴费。
4)根据缴费人员选择的缴费选项生成一条合并的账单,并计算金额。
5)缴费项目分为四个状态:草稿、未开始、进行中、已关闭。只有草稿状态可以编辑缴费信息,选够项,已经生成账单。
核心类
- FeeItem: 表示一个具体的缴费项目。
- FeeOption: 表示一个缴费项目的具体选项。
- Person: 表示一个缴费人员。
- Bill: 表示每个人的账单,包括选择的缴费项和总金额。
- FeeManager: 管理所有的缴费项目、选项和账单生成。
- 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());
}