📖 目录
-
前言
-
什么是命令模式
-
案例背景:虚拟仿真实验中的操作管理
-
案例效果图(示意)
-
代码实现
-
5.1 命令接口:ICommand
-
5.2 具体命令类:HeatCommand / CoolCommand
-
5.3 调用者:CommandInvoker
-
5.4 接收者:WaterHeater
-
5.5 UI 控制:按钮触发命令
-
-
运行流程
-
注意事项总结
-
扩展思考
-
总结
1. 前言
在虚拟仿真实验中,实验对象的操作可能需要:
-
记录操作顺序
-
撤销/重做操作
-
队列化操作执行
如果直接在 UI 里写逻辑,操作管理会混乱。
命令模式(Command Pattern) 可以把操作封装成对象,使得操作可 记录、撤销、排队 ,且 调用者与接收者解耦。
2. 什么是命令模式
命令模式:将一个请求封装成对象,从而使你可用不同的请求、队列化请求或记录请求日志,以及支持可撤销操作。
优点:
-
解耦调用者和接收者
-
可以记录、撤销或重做操作
-
易于扩展新操作
3. 案例背景:虚拟仿真实验中的操作管理
-
实验对象:水壶
-
可操作行为:
-
加热(HeatCommand)
-
冷却(CoolCommand)
-
-
UI 点击按钮 → 创建命令 → 执行
-
可以撤销操作 → 返回上一个状态
4. 案例效果图(示意)
cs
[加热按钮] → HeatCommand → 水温升高
[冷却按钮] → CoolCommand → 水温下降
[撤销按钮] → 回到上一个状态
5. 代码实现
5.1 命令接口:ICommand
cs
public interface ICommand
{
void Execute();
void Undo();
}
5.2 具体命令类
HeatCommand
cs
using UnityEngine;
public class HeatCommand : ICommand
{
private WaterHeater receiver;
private float previousTemp;
public HeatCommand(WaterHeater receiver)
{
this.receiver = receiver;
}
public void Execute()
{
previousTemp = receiver.Temperature;
receiver.Heat();
}
public void Undo()
{
receiver.SetTemperature(previousTemp);
}
}
CoolCommand
cs
using UnityEngine;
public class CoolCommand : ICommand
{
private WaterHeater receiver;
private float previousTemp;
public CoolCommand(WaterHeater receiver)
{
this.receiver = receiver;
}
public void Execute()
{
previousTemp = receiver.Temperature;
receiver.Cool();
}
public void Undo()
{
receiver.SetTemperature(previousTemp);
}
}
5.3 调用者:CommandInvoker
cs
using System.Collections.Generic;
public class CommandInvoker
{
private Stack<ICommand> commandHistory = new Stack<ICommand>();
public void ExecuteCommand(ICommand command)
{
command.Execute();
commandHistory.Push(command);
}
public void Undo()
{
if (commandHistory.Count > 0)
{
ICommand command = commandHistory.Pop();
command.Undo();
}
}
}
5.4 接收者:WaterHeater
cs
using UnityEngine;
public class WaterHeater : MonoBehaviour
{
public float Temperature { get; private set; } = 20f;
public void Heat()
{
Temperature += 10f;
Debug.Log($"加热中,温度:{Temperature}℃");
}
public void Cool()
{
Temperature -= 10f;
Debug.Log($"冷却中,温度:{Temperature}℃");
}
public void SetTemperature(float temp)
{
Temperature = temp;
Debug.Log($"撤销操作,温度恢复:{Temperature}℃");
}
}
5.5 UI 控制:按钮触发命令
cs
using UnityEngine;
using UnityEngine.UI;
public class CommandUI : MonoBehaviour
{
[SerializeField] private Button heatButton;
[SerializeField] private Button coolButton;
[SerializeField] private Button undoButton;
[SerializeField] private WaterHeater waterHeater;
private CommandInvoker invoker = new CommandInvoker();
private void Start()
{
heatButton.onClick.AddListener(() =>
{
invoker.ExecuteCommand(new HeatCommand(waterHeater));
});
coolButton.onClick.AddListener(() =>
{
invoker.ExecuteCommand(new CoolCommand(waterHeater));
});
undoButton.onClick.AddListener(() =>
{
invoker.Undo();
});
}
}
6. 运行流程
-
玩家点击 加热按钮 → 创建 HeatCommand → 执行 → 温度升高
-
玩家点击 冷却按钮 → 创建 CoolCommand → 执行 → 温度下降
-
玩家点击 撤销按钮 → 弹出栈顶命令 → 调用 Undo → 恢复上一次状态
7. 注意事项总结
-
撤销操作需记录状态:在 Execute 前保存当前状态
-
命令对象独立:命令类只调用接收者方法,不处理 UI
-
调用者解耦接收者:UI 或系统只与 CommandInvoker 交互
8. 扩展思考
-
可以结合 对象池模式,回收命令对象,减少 GC
-
可以记录操作序列 → 实现实验回放
-
可以结合 观察者模式 → UI 或日志自动更新
9. 总结
通过这个虚拟仿真案例,你学会了:
-
使用 命令模式 封装实验操作
-
支持撤销操作,操作管理清晰
-
调用者和接收者解耦,易于扩展新操作
👉 命令模式在虚拟实验系统中,非常适合操作管理、撤销与回放功能,提升实验交互体验。