11.23 实验十五职责链模式 实验十六命令模式

实验15:职责链模式
本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:
1、理解职责链模式的动机,掌握该模式的结构;
2、能够利用职责链模式解决实际问题。

[实验任务一]:财务审批
某物资管理系统中物资采购需要分级审批,主任可以审批1万元及以下的采购单,部门经理可以审批5万元及以下的采购单,副总经理可以审批10万元及以下的采购单,总经理可以审批20万元及以下的采购单,20万元以上的采购单需要开职工大会确定。现用职责链模式设计该系统。
实验要求:

  1. 提交类图;
  2. 提交源代码;
  3. 注意编程规范。

image

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()操作,可以使用加法运算来模拟实现。
实验要求:

  1. 提交类图;
  2. 提交源代码;
  3. 注意编程规范。

image

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();
    }}
posted @ 2026-01-03 13:33  liu某人  阅读(0)  评论(0)    收藏  举报