2013-03-24 16 views
6

Obecnie studiuję wzorce projektowe i obecnie patrzę na wzór polecenia.W języku C# jak poprawnie wdrożyć wzorzec projektowania polecenia?

Tu jest mój bieżący kod:

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

Zauważ, że w moim główne metody, można uzyskać dostęp do metody odbiornika, który jest zdolny do ustawienia, które polecenie, aby korzystać z SetAction.

Moje pytanie brzmi: czy moja implementacja narusza cel wzorca polecenia i czy moja implementacja jest zła, ponieważ jestem w stanie uzyskać do niego dostęp w moim kodzie klienta? Jeśli tak, jak mogę poprawić tę implementację.

+0

Dlaczego rigamarole z CommandOptions enum i metody skomplikowane Calculator.GetResult()? –

+1

Ten odnośnik może być przydatny, zarówno w odniesieniu do wzorca polecenia, jak i innych wzorców projektowych, nad którymi pracowałeś: http://www.dofactory.com/Patterns/PatternCommand.aspx. –

+1

chciałbym zachęcić do zapoznania się te artykuły ... [.NET Junkie poleceń Architektura] (http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=91) i [.NET Junkie Query Architektura] (http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=92) – TylerOhlsen

Odpowiedz

7

Zrobiłem ujęcie edycji tekstu (tj. Nie uruchomiłem go, oczekuję błędów składniowych :)) Twój kod. Oto jak modelowałbym twój problem.

Niektóre points-

1) Czy polecenie wykonać działanie. W twoim przypadku masz klasy poleceń, ale kalkulator zawiera logikę do obliczeń. Zamiast tego, obuduj akcję komend wewnątrz samej klasy poleceń: 2) Ustawiłem fabrykę, aby zamapować opcję polecenia na komendę i zapisać kilka wierszy, usuwając break s, ponieważ mogę zwrócić komendę.

3) IReceiver przechowuje obecnie wartości przekazywane do polecenia. W tym przypadku, ponieważ nasi operatorzy są binarni, właśnie użyłem X i Y. Może to być tablica lub jakikolwiek inny typ złożony w innych przypadkach.

4) Wyliczenie nie jest wymagane, chyba że absolutnie chcesz.

Edit Na ponowne spojrzenie, myślę, że jeszcze lepszym rozwiązaniem byłoby, aby nie zarejestrować odbiornik z poleceniami, zamiast przechodzić na parametry podczas wywoływania polecenia.

//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(); 
    } 
} 
Powiązane problemy