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メイン メソッドでは、使用するコマンドを設定できるレシーバーのメソッドにアクセスできることに注意してください。

私の質問は次のとおりです。私の実装はコマンド パターンの目的に違反していますか?クライアント コードでアクセスできるため、私の実装は間違っていますか? もしそうなら、どうすればこの実装を改善できますか。

4

1 に答える 1

9

テキスト編集のショットを撮りました(つまり、実行していません。構文エラーが予想されます:))コード。これが私があなたの問題をモデル化する方法です。

いくつかの点-

1) コマンドにアクションを実行させます。あなたの場合、コマンドクラスがありますが、電卓は計算のロジックを保持しています。むしろ、コマンド クラス自体の中にコマンド アクションをカプセル化します。

break2) コマンド オプションをコマンドにマップするファクトリを配置し、コマンドを返すことができるため、s を削除して数行を節約しました。

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();
    }
}
于 2013-03-24T15:52:35.380 に答える