11.23 实验十五职责链模式 实验十六命令模式
实验15:职责链模式
本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:
1、理解职责链模式的动机,掌握该模式的结构;
2、能够利用职责链模式解决实际问题。
[实验任务一]:财务审批
某物资管理系统中物资采购需要分级审批,主任可以审批1万元及以下的采购单,部门经理可以审批5万元及以下的采购单,副总经理可以审批10万元及以下的采购单,总经理可以审批20万元及以下的采购单,20万元以上的采购单需要开职工大会确定。现用职责链模式设计该系统。
实验要求:
- 提交类图;
- 提交源代码;
- 注意编程规范。

public class PurchaseRequest {
// 采购单编号
private final int id;
// 采购金额
private final double amount;
// 采购描述
private final String description;
/**
* 构造方法:初始化采购请求信息
* @param id 采购单编号
* @param amount 采购金额
* @param description 采购描述
*/
public PurchaseRequest(int id, double amount, String description) {
this.id = id;
this.amount = amount;
this.description = description;
}
// getter方法
public int getId() {
return id;
}
public double getAmount() {
return amount;
}
public String getDescription() {
return description;
}}
public abstract class Approver {
// 审批者姓名
protected String name;
// 下一个审批者(职责链的下一环)
protected Approver nextApprover;
/**
* 构造方法:初始化审批者姓名
* @param name 审批者姓名
*/
public Approver(String name) {
this.name = name;
}
/**
* 设置下一个审批者
* @param nextApprover 下一个审批者实例
*/
public void setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
}
/**
* 抽象审批方法:子类必须实现具体审批逻辑
* @param request 采购请求
*/
public abstract void processRequest(PurchaseRequest request);}
public class Director extends Approver {
public Director(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
double amount = request.getAmount();
// 权限判断:≤1万由主任审批
if (amount <= 10000) {
System.out.println("=== 采购单审批结果 ===");
System.out.println("采购单编号:" + request.getId());
System.out.println("采购金额:" + amount + "元");
System.out.println("采购描述:" + request.getDescription());
System.out.println("审批人:" + name + "(主任)");
System.out.println("审批结果:批准");
System.out.println("=====================\n");
} else {
// 超出权限,转发给下一个审批者
if (nextApprover != null) {
System.out.println(name + "(主任):采购金额" + amount + "元超出我的审批权限(≤1万),转交给" + nextApprover.name + "审批\n");
nextApprover.processRequest(request);
}
}
}}
public class DeptManager extends Approver {
public DeptManager(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
double amount = request.getAmount();
// 权限判断:1万<金额≤5万由部门经理审批
if (amount > 10000 && amount <= 50000) {
System.out.println("=== 采购单审批结果 ===");
System.out.println("采购单编号:" + request.getId());
System.out.println("采购金额:" + amount + "元");
System.out.println("采购描述:" + request.getDescription());
System.out.println("审批人:" + name + "(部门经理)");
System.out.println("审批结果:批准");
System.out.println("=====================\n");
} else {
// 超出权限,转发给下一个审批者
if (nextApprover != null) {
System.out.println(name + "(部门经理):采购金额" + amount + "元超出我的审批权限(≤5万),转交给" + nextApprover.name + "审批\n");
nextApprover.processRequest(request);
}
}
}}
/**
* 副总经理:审批10万元及以下采购单
*/public class ViceGeneralManager extends Approver {
public ViceGeneralManager(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
double amount = request.getAmount();
// 权限判断:5万<金额≤10万由副总经理审批
if (amount > 50000 && amount <= 100000) {
System.out.println("=== 采购单审批结果 ===");
System.out.println("采购单编号:" + request.getId());
System.out.println("采购金额:" + amount + "元");
System.out.println("采购描述:" + request.getDescription());
System.out.println("审批人:" + name + "(副总经理)");
System.out.println("审批结果:批准");
System.out.println("=====================\n");
} else {
// 超出权限,转发给下一个审批者
if (nextApprover != null) {
System.out.println(name + "(副总经理):采购金额" + amount + "元超出我的审批权限(≤10万),转交给" + nextApprover.name + "审批\n");
nextApprover.processRequest(request);
}
}
}}
/**
* 总经理:审批20万元及以下采购单
*/public class GeneralManager extends Approver {
public GeneralManager(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
double amount = request.getAmount();
// 权限判断:10万<金额≤20万由总经理审批
if (amount > 100000 && amount <= 200000) {
System.out.println("=== 采购单审批结果 ===");
System.out.println("采购单编号:" + request.getId());
System.out.println("采购金额:" + amount + "元");
System.out.println("采购描述:" + request.getDescription());
System.out.println("审批人:" + name + "(总经理)");
System.out.println("审批结果:批准");
System.out.println("=====================\n");
} else {
// 超出权限,转发给下一个审批者(职工大会)
if (nextApprover != null) {
System.out.println(name + "(总经理):采购金额" + amount + "元超出我的审批权限(≤20万),转交给" + nextApprover.name + "审议\n");
nextApprover.processRequest(request);
}
}
}}
**
* 职工大会:最终审批者,处理20万元以上采购单
*/public class StaffMeeting extends Approver {
public StaffMeeting(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
double amount = request.getAmount();
// 最终处理:20万以上由职工大会审议
System.out.println("=== 采购单审批结果 ===");
System.out.println("采购单编号:" + request.getId());
System.out.println("采购金额:" + amount + "元");
System.out.println("采购描述:" + request.getDescription());
System.out.println("审批机构:" + name + "(职工大会)");
System.out.println("审批结果:经职工大会投票审议,批准采购");
System.out.println("=====================\n");
}}
/**
* 测试类:验证职责链模式的审批流程
*/public class ApprovalTest {
public static void main(String[] args) {
// 1. 创建各审批者实例
Approver director = new Director("张三");
Approver deptManager = new DeptManager("李四");
Approver viceGM = new ViceGeneralManager("王五");
Approver gm = new GeneralManager("赵六");
Approver staffMeeting = new StaffMeeting("公司职工大会");
// 2. 构建职责链:主任→部门经理→副总经理→总经理→职工大会
director.setNextApprover(deptManager);
deptManager.setNextApprover(viceGM);
viceGM.setNextApprover(gm);
gm.setNextApprover(staffMeeting);
// 3. 创建不同金额的采购请求
PurchaseRequest request1 = new PurchaseRequest(1001, 8000, "采购办公电脑5台");
PurchaseRequest request2 = new PurchaseRequest(1002, 35000, "采购办公打印机10台");
PurchaseRequest request3 = new PurchaseRequest(1003, 85000, "采购服务器2台");
PurchaseRequest request4 = new PurchaseRequest(1004, 150000, "采购办公家具一批");
PurchaseRequest request5 = new PurchaseRequest(1005, 250000, "采购新办公场地设备");
// 4. 发起审批(从职责链起点开始)
System.out.println("===== 发起采购审批 =====");
director.processRequest(request1);
director.processRequest(request2);
director.processRequest(request3);
director.processRequest(request4);
director.processRequest(request5);
}}
实验16:命令模式
本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:
1、理解命令模式的动机,掌握该模式的结构;
2、能够利用命令模式解决实际问题。
[实验任务一]:多次撤销和重复的命令模式
某系统需要提供一个命令集合(注:可以使用链表,栈等集合对象实现),用于存储一系列命令对象,并通过该命令集合实现多次undo()和redo()操作,可以使用加法运算来模拟实现。
实验要求:
- 提交类图;
- 提交源代码;
- 注意编程规范。

public class Calculator {
// 当前计算结果,初始值为0
private int currentValue = 0;
/**
* 加法运算
* @param value 要添加的数值
*/
public void add(int value) {
currentValue += value;
}
/**
* 减法运算(用于撤销加法)
* @param value 要减去的数值(与加法数值一致)
*/
public void subtract(int value) {
currentValue -= value;
}
/**
* 获取当前计算结果
* @return 当前数值
*/
public int getCurrentValue() {
return currentValue;
}}
/**
* 抽象命令接口:定义命令的核心行为(执行、撤销、重复)
*/public interface Command {
/**
* 执行命令
*/
void execute();
/**
* 撤销命令
*/
void undo();
/**
* 重复命令(重新执行)
*/
void redo();}
/**
* 具体命令:加法命令,将加法请求转换为计算器的操作
*/public class AddCommand implements Command {
// 持有接收者(计算器)引用
private final Calculator calculator;
// 加法运算的数值(命令的状态信息)
private final int value;
/**
* 构造方法:绑定计算器和加法数值
* @param calculator 计算器实例
* @param value 要添加的数值
*/
public AddCommand(Calculator calculator, int value) {
this.calculator = calculator;
this.value = value;
}
@Override
public void execute() {
// 执行加法:调用计算器的add方法
calculator.add(value);
}
@Override
public void undo() {
// 撤销加法:调用计算器的subtract方法(反向操作)
calculator.subtract(value);
}
@Override
public void redo() {
// 重复加法:重新执行execute方法
execute();
}}
import java.util.Stack;
/**
* 调用者:命令管理器,负责命令的执行、撤销、重复管理
*/public class CommandManager {
// 存储已执行的命令(用于undo)
private final Stack<Command> executedCommands = new Stack<>();
// 存储已撤销的命令(用于redo)
private final Stack<Command> undoneCommands = new Stack<>();
/**
* 执行命令
* @param command 要执行的命令
*/
public void executeCommand(Command command) {
if (command != null) {
command.execute();
executedCommands.push(command);
// 执行新命令后,清空已撤销命令栈(避免redo无效命令)
undoneCommands.clear();
}
}
/**
* 撤销上一次命令
* @return 撤销成功返回true,无命令可撤销返回false
*/
public boolean undo() {
if (!executedCommands.isEmpty()) {
Command command = executedCommands.pop();
command.undo();
undoneCommands.push(command);
return true;
}
System.out.println("⚠️ 无命令可撤销!");
return false;
}
/**
* 重复上一次撤销的命令
* @return 重复成功返回true,无命令可重复返回false
*/
public boolean redo() {
if (!undoneCommands.isEmpty()) {
Command command = undoneCommands.pop();
command.redo();
executedCommands.push(command);
return true;
}
System.out.println("⚠️ 无命令可重复!");
return false;
}}
/**
* 测试类:验证命令模式的执行、多次undo和redo功能
*/public class CommandTest {
public static void main(String[] args) {
// 1. 创建接收者(计算器)和调用者(命令管理器)
Calculator calculator = new Calculator();
CommandManager commandManager = new CommandManager();
System.out.println("===== 初始状态 =====");
System.out.println("当前计算结果:" + calculator.getCurrentValue() + "\n");
// 2. 执行一系列加法命令
Command add5 = new AddCommand(calculator, 5);
Command add3 = new AddCommand(calculator, 3);
Command add10 = new AddCommand(calculator, 10);
System.out.println("===== 执行命令:+5 =====");
commandManager.executeCommand(add5);
System.out.println("当前计算结果:" + calculator.getCurrentValue() + "\n");
System.out.println("===== 执行命令:+3 =====");
commandManager.executeCommand(add3);
System.out.println("当前计算结果:" + calculator.getCurrentValue() + "\n");
System.out.println("===== 执行命令:+10 =====");
commandManager.executeCommand(add10);
System.out.println("当前计算结果:" + calculator.getCurrentValue() + "\n");
// 3. 多次undo
System.out.println("===== 撤销一次(undo) =====");
commandManager.undo();
System.out.println("当前计算结果:" + calculator.getCurrentValue() + "\n");
System.out.println("===== 再撤销一次(undo) =====");
commandManager.undo();
System.out.println("当前计算结果:" + calculator.getCurrentValue() + "\n");
// 4. 多次redo
System.out.println("===== 重复一次(redo) =====");
commandManager.redo();
System.out.println("当前计算结果:" + calculator.getCurrentValue() + "\n");
System.out.println("===== 再重复一次(redo) =====");
commandManager.redo();
System.out.println("当前计算结果:" + calculator.getCurrentValue() + "\n");
// 5. 边界测试:无命令可undo/redo
System.out.println("===== 尝试撤销第三次(无命令可撤销) =====");
commandManager.undo();
commandManager.undo();
commandManager.undo();
System.out.println("\n===== 尝试重复第三次(无命令可重复) =====");
commandManager.redo();
commandManager.redo();
}}

浙公网安备 33010602011771号