C# 命令模式 (Command Pattern) 完整实例与解析

苏见山
苏见山
发布时间:2026-10-14 | 4人浏览过
原创

文章通过智能家居遥控器的构建过程,深入解析 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# 设计模式的应用资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表