C# 设计模式系列教程-命令模式

C# 设计模式系列教程-命令模式

什么是命令模式

命令模式是一种行为设计模式,它能把请求或操作封装起来,以便在不同上下文中进行参数化、延迟执行或支持撤销操作。命令模式把命令的发送者和接收者解耦,并且把命令操作封装成对象,这些对象可以用队列进行管理。

在命令模式中,任何对象都可以扮演“命令”的角色,唯一的要求是具备两项能力:

  1. 执行这个请求的操作。
  2. 把请求的接收者传递到执行的操作中。

通常情况下,会为每一种命令都创建一个类,这个类包含了接收者以及需要执行的方法。

命令模式的实现

命令模式的实现包含如下角色:

  • Command(抽象命令类):声明了一组用于执行操作的抽象方法,通常包含 Execute()Undo(),其中 Execute() 方法用于执行具体的命令操作,Undo() 方法用于撤销该操作。
  • ConcreteCommand(具体命令类):继承了 Command,实现了抽象方法,可以定义自己的逻辑来处理请求,并且可以保持一些额外的状态变量。
  • Invoker(调用者):会持有一个命令对象,并且在需要的时候,通过调用 Execute() 方法来触发命令。
  • Receiver(接收者):这个对象会实现具体的业务逻辑,并且能够完成 Command 对象需要执行的任何操作。此外,它们为 Command 对象提供了执行操作所需的任何上下文信息。

设计模式示例说明

示例一

假设我们现在有一个遥控器,它有若干个按钮可以控制电器。

我们可以使用命令模式来实现这个功能。

  1. 创建 Command 接口:
public interface ICommand
{
    void Execute();
    void Undo();
}

其中 ExecuteUndo 方法定义了我们需要的操作。

  1. 创建 Light 类作为接收者:
public class Light
{
    public void On() { Console.WriteLine("Light is on"); }
    public void Off() { Console.WriteLine("Light is off"); }
}

这个类表示了我们要控制的电器。

  1. 创建具体命令类 LightOnCommandLightOffCommand
public class LightOnCommand : ICommand
{
    private readonly Light _light;

    public LightOnCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.On();
    }

    public void Undo()
    {
        _light.Off();
    }
}

public class LightOffCommand : ICommand
{
    private readonly Light _light;

    public LightOffCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.Off();
    }

    public void Undo()
    {
        _light.On();
    }
}
  1. 创建 RemoteControl 类作为调用者:
public class RemoteControl
{
    private readonly ICommand[] _onCommands;
    private readonly ICommand[] _offCommands;

    public RemoteControl()
    {
        _onCommands = new ICommand[7];
        _offCommands = new ICommand[7];

        // 初始化命令数组
        for (var i = 0; i < 7; i++)
        {
            _onCommands[i] = new NoCommand();
            _offCommands[i] = new NoCommand();
        }
    }

    public void SetCommand(int slot, ICommand onCommand, ICommand offCommand)
    {
        _onCommands[slot] = onCommand;
        _offCommands[slot] = offCommand;
    }

    public void OnButtonWasPushed(int slot)
    {
        _onCommands[slot].Execute();
    }

    public void OffButtonWasPushed(int slot)
    {
        _offCommands[slot].Execute();
    }
}

这个类实例化一个 ICommand 数组,同时实现了 SetCommandOnButtonWasPushedOffButtonWasPushed 方法。当执行某个命令时,会调用相应的 Execute 方法。

  1. 编写测试代码:
var remoteControl = new RemoteControl();

var light = new Light();
var lightOnCommand = new LightOnCommand(light);
var lightOffCommand = new LightOffCommand(light);

remoteControl.SetCommand(0, lightOnCommand, lightOffCommand);

remoteControl.OnButtonWasPushed(0); // Light is on
remoteControl.OffButtonWasPushed(0); // Light is off

通过测试代码的执行,我们可以实现控制电器打开和关闭的功能。

示例二

我们现在来实现一个简单的遥控器,它有两个按钮:一个按钮用来开门,另一个按钮用来关门。同时,我们需要实现撤销功能,可以撤销最后一个操作。

  1. 创建 Door 类作为接收者:
public class Door
{
    private bool _isOpen;

    public bool IsOpen() => _isOpen;

    public void Open()
    {
        Console.WriteLine("Door is open");
        _isOpen = true;
    }

    public void Close()
    {
        Console.WriteLine("Door is closed");
        _isOpen = false;
    }
}

这个类表示了我们要控制的门。

  1. 创建具体命令类 OpenDoorCommandCloseDoorCommand
public class OpenDoorCommand : ICommand
{
    private readonly Door _door;

    public OpenDoorCommand(Door door)
    {
        _door = door;
    }

    public void Execute()
    {
        _door.Open();
    }

    public void Undo()
    {
        _door.Close();
    }
}

public class CloseDoorCommand : ICommand
{
    private readonly Door _door;

    public CloseDoorCommand(Door door)
    {
        _door = door;
    }

    public void Execute()
    {
        _door.Close();
    }

    public void Undo()
    {
        _door.Open();
    }
}
  1. 创建 SimpleRemoteControl 类作为调用者:
public class SimpleRemoteControl
{
    private ICommand _lastCommand;

    public void SetCommand(ICommand command)
    {
        _lastCommand = command;
    }

    public void ButtonWasPressed()
    {
        _lastCommand.Execute();
    }

    public void UndoButtonWasPressed()
    {
        _lastCommand.Undo();
    }
}

这个类实现了 SetCommandButtonWasPressedUndoButtonWasPressed 方法。同时,还用一个成员变量 _lastCommand 记录最后一次执行的命令。

  1. 编写测试代码:
var door = new Door();
var openCommand = new OpenDoorCommand(door);
var closeCommand = new CloseDoorCommand(door);

var remote = new SimpleRemoteControl();

remote.SetCommand(openCommand);
remote.ButtonWasPressed(); // Door is open
remote.UndoButtonWasPressed(); // Door is closed

remote.SetCommand(closeCommand);
remote.ButtonWasPressed(); // Door is closed
remote.UndoButtonWasPressed(); // Door is open

通过测试代码的执行,我们可以实现开门、关门以及撤销功能。

总结

命令模式能够把一个请求封装为一个对象,并且能够进行动态地参数化、队列化、简单的请求或撤销。通过使用这个模式,我们可以将发出命令的对象和执行命令的对象进行解耦。同时,命令模式还能够维护一组对象,这些对象能够随时添加、删除或替换。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 设计模式系列教程-命令模式 - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • javascript深拷贝的原理与实现方法分析

    JavaScript深拷贝的原理与实现方法分析 在JavaScript中,一个对象的同名属性可以有多个引用。当一个对象被拷贝时,只是拷贝了引用,而不是对象本身。这种拷贝称为浅拷贝。浅拷贝的问题在于如果原始对象中某个属性是一个对象,那么在拷贝对象中的该属性也只是一个对象的引用,当原始对象中的该属性发生改变时,拷贝对象中的该属性也会改变。想要避免这个问题,需要用…

    C# 2023年6月8日
    00
  • Asp.net(C#)实现验证码功能代码

    接下来我将为您详细讲解Asp.net(C#)实现验证码功能代码的完整攻略。 1. 简介 验证码,就是为了防止恶意机器人向网站提交请求或恶意注册而设计的一种验证方法。通过验证码,网站可以判断请求来源的真实性并提高安全性。 2. 实现过程 首先,我们需要生成一个随机的验证码,并将其显示在前台;其次,用户需要输入验证码并进行验证。下面,我将分两部分进行详细讲解。 …

    C# 2023年5月31日
    00
  • 使用Log4net进行日志记录

    使用Log4net进行日志记录是一项非常重要的任务,因为它可以帮助开发者更好地了解应用程序的运行状态,检测并解决在调试和测试期间遇到的问题。下面就是关于如何使用Log4net进行日志记录的完整攻略: 步骤一:安装Log4net 首先,你需要在你的应用程序中下载并安装Log4net。你可以在NuGet管理器中搜索“log4net”,然后安装最新版本。 步骤二:…

    C# 2023年5月15日
    00
  • ASP.NET中制作各种3D图表的方法

    制作各种3D图表,在ASP.NET中可以分为两类:使用前端JavaScript库和通过ASP.NET后端组件渲染3D图表。 使用前端JavaScript库 Three.js Three.js是一种流行的JavaScript库,它提供了一个轻量级的3D引擎,易于使用和构建高质量的3D应用程序。由于Three.js是一个开源库,因此它可以免费使用,并且拥有广泛的…

    C# 2023年6月3日
    00
  • c# 用ICSharpCode组件压缩文件

    下面是详细讲解“c# 用ICSharpCode组件压缩文件”的完整攻略。 一、ICSharpCode组件简介 ICSharpCode是一个.NET开发者常用的开源项目,其中包括ICSharpCode.SharpZipLib组件,可以用来对压缩文件进行操作,包括压缩和解压缩。如果想要在C#中实现压缩和解压缩,可以通过使用ICSharpCode.SharpZip…

    C# 2023年6月1日
    00
  • ASP.NET Core – 缓存之分布式缓存

    分布式缓存是由多个应用服务器共享的缓存,通常作为访问它的应用服务器的外部服务进行维护。 分布式缓存可以提高 ASP.NET Core 应用的性能和可伸缩性,尤其是当应用由云服务或服务器场托管时。 与其他将缓存数据存储在单个应用服务器上的缓存方案相比,分布式缓存具有多个优势。 当分发缓存数据时,数据: 在多个服务器的请求之间保持一致(一致性)。 在进行服务器重…

    C# 2023年4月19日
    00
  • 使用PowerShell .Net获取电脑中的UUID

    使用PowerShell .Net获取电脑中的UUID 在Windows系统中,每台计算机都有唯一的标识符UUID(Universally Unique Identifier),可以用于识别计算机。使用PowerShell .Net可以轻松获取计算机的UUID。 步骤 打开PowerShell环境。在开始菜单中搜索“PowerShell”并打开。 在Powe…

    C# 2023年6月3日
    00
  • C#设置Word文本框中改变文字方向的方法

    下面是“C#设置Word文本框中改变文字方向的方法”的详细攻略。 一、背景说明 在进行Word文档的编写时,有时需要设置文本框中文字的方向。一般情况下,默认情况下文字方向是水平方向,如果我们想将文本框中文字方向改为垂直方向,就需要进行相关的设置。 二、文字方向的设置方法 在C#代码中,我们可以通过使用Microsoft.Office.Interop.Word…

    C# 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部