C# 命令模式 (Command Pattern) 完整实例与解析
文章通过智能家居遥控器的构建过程,深入解析 C# 命令模式。核心在于将操作方法封装为独立的 Command 对象,通过统一接口实现解耦,使调用者与执行者互不依赖。
目标与准备
假设我们需要开发一个万能遥控器,能够控制电灯(Light)和电视机(Tv)的开关及切换频道。如果直接让遥控器调用设备的 TurnOn() 或 TurnOff() 方法,会导致调用逻辑侵入设备类,且难以扩展新的电器。
命令模式的核心目标是将“请求”封装为一个对象,从而让你用不同的请求对客户端进行参数化。在此场景下,我们需要将每一次按键动作抽象为一个命令对象。
真实操作顺序
第1步:定义命令接口
目的:确立所有命令的统一契约,确保遥控器无需知道具体是哪种设备被控制。
创建一个名为 IControl 的接口,定义唯一的执行方法 Execute()。所有具体的电器操作都将实现此接口。
public interface IControl
{
void Execute();
}
第2步:定义命令接收者(Receiver)
目的:提供实际的业务逻辑执行者,即具备开、关、切换功能的实体类。
这里定义 Tv 和 Light 类,包含各自的具体操作方法。注意:Light 类中的打开方法原文可能存在拼写错误(如 TunrOn),在实际开发中应修正为标准命名 TurnOn。
public class Tv
{
public void TurnOn()
{
Console.WriteLine("电视机打开了");
}
public void TurnOff()
{
Console.WriteLine("电视机关闭了");
}
public void SwitchChannel()
{
Console.WriteLine("电视机切换频道");
}
}
public class Light
{
public void TurnOn()
{
Console.WriteLine("电灯打开了");
}
public void TurnOff()
{
Console.WriteLine("电灯关闭了");
}
}
第3步:实现具体命令类(Concrete Command)
目的:将接收者的方法与接口的 Execute 绑定。每个命令类持有一个接收者引用,并在执行时委托给接收者。
分别创建 LighOn, LightOff, TvOn, TvOff, TvSwitch 等类,实现 IControl 接口。
public class LighOn : IControl
{
private Light _light;
public LighOn(Light light)
{
_light = light;
}
public void Execute()
{
_light.TurnOn(); // 确保此处调用的是正确的 TurnOn
}
}
public class LightOff : IControl
{
private Light _light;
public LightOff(Light light)
{
_light = light;
}
public void Execute()
{
_light.TurnOff();
}
}
// TV 相关命令类似...\npublic class TvOn : IControl
{
private Tv _tv;
public TvOn(Tv tv)
{
_tv = tv;
}
public void Execute()
{
_tv.TurnOn();
}
}
第4步:组装控制器(Invoker)
目的:遥控器作为调用者,负责存储和触发命令,而不关心命令内部是如何执行的。
创建 RemoteControl 类,使用集合(如 List<IControl>)来存储不同的命令对象。提供添加命令和触发按钮的方法。
public class RemoteControl
{
private List<IControl> onCommands = new List<IControl>();
private List<IControl> offCommands = new List<IControl>();
private List<IControl> switchCommands = new List<IControl>();
public void AddOnCommand(IControl control)
{
onCommands.Add(control);
}
public void PressOnButton(int index)
{
if(index < onCommands.Count)
{
onCommands[index].Execute();
}
}
// 其他按钮触发逻辑类似...
}
第5步:客户端调用测试
目的:组装所有组件,验证命令模式的运行效果。
在 Main 方法中,实例化接收者(TV/灯),实例化具体的命令对象并注入接收者,最后将这些命令注册到遥控器中。点击按钮时,遥控器仅调用 Execute()。
class Program
{
static void Main(string[] args)
{
// 1. 创建接收者
Light light = new Light();
Tv tv = new Tv();
// 2. 创建具体命令(将接收者注入命令)
IControl turnLightOn = new LighOn(light);
IControl turnTvOn = new TvOn(tv);
IControl turnTvSwitch = new TvSwitch(tv);
// 3. 组装遥控器
RemoteControl remote = new RemoteControl();
remote.AddOnCommand(turnLightOn);
remote.AddOnCommand(turnTvOn);
remote.AddSwitchCommand(turnTvSwitch);
// 4. 触发命令
remote.PressOnButton(0); // 打开灯
remote.PressOnButton(1); // 打开电视
remote.PressSwitchButton(0); // 切换电视频道
Console.ReadKey();
}
}
完成判断
当程序运行后,控制台按预期输出对应电器的状态变更(如“电灯打开了”),且 RemoteControl 类中没有出现 Light 或 Tv 的具体类型引用,仅依赖于 IControl 接口,证明解耦成功。
简要总结
命令模式通过将请求封装成对象,实现了以下价值:
- 解耦:调用者(遥控器)不需要知道接收者(电器)的具体细节。
- 扩展性:新增电器只需新增对应的 Command 类并实现接口,无需修改遥控器代码。
- 灵活性:易于实现队列请求、日志记录和撤销操作(需额外扩展 Command 类)。
以上就是 C# 命令模式 (Command Pattern) 的详细内容,更多关于 C# 设计模式的应用资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









