在C#中,我如何正确实现命令设计模式?

8

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

这是我的当前代码:

// 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方法,该方法能够设置要使用的命令。
我的问题是:我的实现是否违反了命令模式的目的?因为我能够在客户端代码中访问它,所以我的实现是否错误?如果是,那么我该如何改进这个实现。

为什么要使用枚举类型CommandOptions和复杂的Calculator.GetResult()方法呢? - Pieter Geerkens
1
你可能会发现这个链接很有用,无论是对于命令模式还是其他你一直在学习的设计模式:http://www.dofactory.com/Patterns/PatternCommand.aspx。 - Matthew Strawbridge
1
我鼓励你阅读这些文章:.NET Junkie Command Architecture.NET Junkie Query Architecture - TylerOhlsen
1个回答

10

我尝试编辑了你的代码(即还未运行,可能会有语法错误 :))。以下是我如何对问题进行建模:

一些要点:

1)让命令执行相应的操作。在您的情况下,您有命令类,但计算器保存了计算逻辑。相反,将命令操作封装在命令类本身中。

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

3)现在,IReceiver保存传递给Command的值。在这种情况下,由于我们的运算符都是二元的,所以我只使用了X和Y。对于其他情况,可以是数组或任何其他复杂类型。

4)除非您绝对需要它,否则不需要枚举。

编辑 重新审视后,我认为更好的解决方案是不要将接收器注册到命令中,而是在调用命令时传递参数。

//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();
    }
}

我认为你的意思是 XXX : ICommand,例如:AddCommand : ICommand - Mehdi Dehghani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接