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日

相关文章

  • .Net的GC垃圾回收原理及实现

    .NET的GC垃圾回收原理及实现 在.NET中,垃圾回收(GC)是一种自动内存管理机制,它负责在运行时自动释放不再使用的内存。在本攻略中,我们将详细讲解.NET的GC垃圾回收原理及实现,并提供两个示例说明。 垃圾回收原理 .NET的GC垃圾回收原理基于以下两个核心概念: 1. 引用计数 引用计数是一种内存管理技术,它通过计算对象的引用数来确定对象是否可以被释…

    C# 2023年5月17日
    00
  • C#基础:Equals()与运算符==的区别分析

    标题:C#基础:Equals()与运算符==的区别分析 简介 在C#编程中,我们经常需要比较两个对象的值是否相等,比如比较两个字符串或数值是否相等等。而比较对象值相等的方式有很多种,比如使用Equals()方法或运算符==。本文将深入分析Equals()方法与运算符==的区别,并提供几个示例来帮助解释。 Equals()方法与运算符==的区别 我们先来简单地…

    C# 2023年6月1日
    00
  • .net连接oracle的3种实现方法

    下面我将详细讲解“.net连接oracle的3种实现方法”的完整攻略。 1. 前言 在使用 C# 进行开发的过程中,我们常常需要连接数据库进行数据的存储、查询和更新等操作。Oracle 数据库是一个非常常见的数据库,以其高效、安全和可靠的特性被广泛使用。而 .NET 作为一种快速高效的编程语言,也能轻松连接到 Oracle 数据库。 本文将介绍 .NET 连…

    C# 2023年6月3日
    00
  • C#中自定义高精度Timer定时器的实例教程

    C#中自定义高精度Timer定时器的实例教程 1. 需求背景 假设我们需要编写一个程序,其中需要在指定的时间间隔内定时执行某个任务,这时我们可以使用系统提供的Timer类来实现,但是,由于Windows系统本身就存在一些限制,因此Timer的精度存在一定的限制,不够高。为了解决这个问题,我们需要自定义高精度Timer定时器。 2. 实现思路 为了实现高精度T…

    C# 2023年6月1日
    00
  • 详解Unity安卓共享纹理

    详解Unity安卓共享纹理 在Unity中,可以使用共享纹理(Shared Texture)技术将应用程序中的纹理共享到其他应用程序中,从而实现数据共享的目的。本文将详细介绍Unity中如何实现安卓共享纹理,并提供两条示例来帮助读者更好地理解。 准备工作 在开始之前,我们需要做一些准备工作: 确保你的Unity版本在2017.1或以上。因为共享纹理技术需要G…

    C# 2023年5月15日
    00
  • C# 如何生成 DataMatrix 格式的二维码

    为了生成 DataMatrix 格式的二维码,我们可以使用 C# 中的 QrCode.Net 库。下面是完整的攻略: 1. 安装 QrCode.Net 库 在 Visual Studio 中,打开工具菜单,选择 NuGet 包管理器,搜索 QrCode.Net 并安装。 2. 导入命名空间 在需要生成二维码的代码文件中,导入 QrCode.Net 命名空间。…

    C# 2023年6月6日
    00
  • C#集合之位数组的用法

    C#集合之位数组的用法 介绍 位数组(BitArray)是C#中的一种特殊集合类型,用于存储0和1位的值,常用于大规模数据的标记和处理。在C#中,位数组是System.Collections命名空间下的一个类,可以通过创建新的BitArray实例来使用和操作。本文将介绍如何使用C#中的位数组,包括创建实例、初始化、添加或修改元素、访问元素、遍历等基本操作。并…

    C# 2023年6月7日
    00
  • 利用C#实现获取当前设备硬件信息

    利用C#实现获取当前设备硬件信息 在C#语言中,可以使用System.Management命名空间下的ManagementObject和ManagementClass来获取设备的硬件信息。下面分步骤讲解如何利用C#实现获取当前设备的硬件信息: 1. 引入System.Management命名空间 在代码中引入System.Management命名空间,如下所…

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