在c#中我如何正确地实现命令设计模式

本文关键字:正确地 实现 命令 设计模式 | 更新日期: 2023-09-27 18:05:28

我目前正在研究设计模式,我目前正在研究命令模式。

下面是我当前的代码:

// this is the receiver
class Calculator : IReceiver
{
    int x;
    int y;
    CommandOptions command;
    public Calculator(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
    public void SetAction(CommandOptions command)
    {
        this.command = command;
    }
    public int GetResult()
    {
        int result = 0;
        switch(this.command)
        {
            case CommandOptions.ADD:
                result = this.x + this.y;
                break;
            case CommandOptions.SUBTRACT:
                result = this.x - this.y;
                break;
            case CommandOptions.MULTIPLY:
                result = this.x * this.y;
                break;
        }
        return result;
    }
}
// command
abstract class Command
{
    protected IReceiver receiver;
    public Command(IReceiver receiver)
    {
        this.receiver = receiver;
    }
    public abstract int Execute();
}
class AddCommand : Command
{
    public AddCommand(IReceiver receiver) : base(receiver)
    {
    }
    public override int Execute()
    {
        reciever.SetAction(CommandOptions.ADD);
        return receiver.GetResult();
    }
}
enum CommandOptions
{
    ADD,
    SUBTRACT,
    MULTIPLY
}
interface IReceiver
{
    void SetAction(CommandOptions command);
    int GetResult();
}

class Program
{
    static void Main(string[] args)
    {
        IReceiver receiver = new Calculator(500, 25);
        //#Issue:The SetAction() method of the receiver is accessible.
        //receiver.SetAction(CommandOptions.ADD);
        receiver.SetAction(CommandOptions.MULTIPLY);
        Command command = null;
        Console.Write("Enter option 1-3: ");
        int commandOption = int.Parse(Console.ReadLine());
        switch(commandOption)
        {
            case 1:
                command = new AddCommand(receiver);
                break;
            case 2:
                command = new SubtractCommand(receiver);
                break;
            case 3:
                command = new MultiplyCommand(receiver);
                break;
            default:
                command = new AddCommand(receiver);
                break;
        }
        Console.WriteLine(command.Execute());
        Console.ReadKey();
    }
}

请注意,在我的主方法中,我可以访问接收器的SetAction方法,该方法能够设置要使用的命令。

我的问题是:我的实现是否违反了命令模式的目的,我的实现是否错误,因为我能够在客户端代码中访问它?如果是这样,我该如何改进这个实现。

在c#中我如何正确地实现命令设计模式

我拍摄了文本编辑(即没有运行它,预计语法错误:))你的代码。以下是我将如何模拟你的问题。

一些点——

1)让命令完成动作。在您的例子中,您有命令类,但是您的计算器保存用于计算的逻辑。而是将命令操作封装在命令类本身

中。

2)我已经设置了一个工厂将命令选项映射到命令,并通过删除break来节省几行,因为我可以返回命令。

3) IReceiver现在保存传递给Command的值。在本例中,由于操作符都是二进制的,所以我只使用了X和y。在其他情况下,可以是数组或任何其他复杂类型。

4) Enum不是必需的,除非你绝对需要它。

编辑重新考虑一下,我认为更好的解决方案是不向命令注册接收器,而是在调用命令时传递参数。

//this is the receiver
class Calculator : IReceiver
{
    int y;
    int x;
    public Calculator(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
    public int Calculate(int commandOption)
    {
        Command command = new CommandFactory().GetCommand(commandOption);
        return command.Execute(x , y);
    }
}

//command
interface ICommand
{    
    int Execute(int x, int y);
}
class AddCommand : Command
{
    public override int Execute(int x, int y)
    {
        return x + y;
    }
}
class MultiplyCommand : Command
{
    public override int Execute(int x, int y)
    {
        return x * y;
    }
}
class SubtractCommand : Command
{
    public override int Execute(int x, int y)
    {
        return x - y;
    }
}
interface IReceiver
{
    int X {get; set;}
    int Y {get; set;}
    int Calculate(int commandOption);
}
public class CommandFactory
{
    public GetCommand(int commandOption)
    {
        switch(commandOption)
        {
            case 1:
                return new AddCommand();
            case 2:
                return new SubtractCommand();
            case 3:
                return new MultiplyCommand();
            default:
                return new AddCommand();
        }       
    }
}
class Program
{
    static void Main(string[] args)
    {
        IReceiver receiver = new Calculator(500, 25);
        //#Issue:The SetAction() method of the receiver is accessible.
        //receiver.SetAction(CommandOptions.ADD);
        //Receiver no longer exposes SetAction
        //receiver.SetAction(CommandOptions.MULTIPLY);
        Console.Write("Enter option 1-3: ");
        int commandOption = int.Parse(Console.ReadLine());
        Console.WriteLine(receiver.Calculate(commandOption));
        Console.ReadKey();
    }
}