2014-04-08 11 views
6

Befehlsmuster ist zum Einkapseln von Befehlen in Objekten. Aber warum nicht stattdessen Funktionszeiger verwenden. Warum muss ich die Klasse Command für jede Operation ableiten? Stattdessen kann ich verschiedene Funktionen haben und diese Funktionen aufrufen, um die Zeiger zu speichern und so weiter ...Befehlsmuster - warum in einem Objekt einkapseln

Antwort

9

Aber warum nicht stattdessen Funktionszeiger verwenden.

Da Funktionszeiger keinen beliebigen Status speichern können. Häufig möchten Sie, dass der Befehl beim Erstellen parametrisiert wird. Zum Beispiel:

struct command { 
    virtual ~command() {} 
    virtual void do_it() = 0; 
}; 

struct say_something : command { 
    // store a message to print later 
    say_something(std::string message) : message(message) {} 

    // print the stored message 
    void do_it() override {std::cout << message << '\n';} 

    std::string message; 
}; 

std::unique_ptr<command> say_hello(new say_something("Hello!")); 

// later 

say_hello->do_it(); // prints stored string 

Wenn Sie einen einfachen Funktionszeiger verwenden wären, dann müssen Sie eine andere Funktion für alles, was Sie können drucken möchten.

Warum muss ich für jede Operation die Klasse Command ableiten?

Weil so Old-School-OOP funktioniert; obwohl, wie oben erwähnt, Sie die Tatsache verwenden können, dass es ein Objekt ist, um es zu parametrisieren, anstatt es zu unterklassifizieren.

Zum Glück moderne C++ hat eine bessere Ausstattung:

typedef std::function<void()> command; 

// print a static string 
command say_hello = []{std::cout << "Hello!\n";}; 

// store a string to print later 
std::string goodbye = "Goodbye!"; 
command say_goodbye = [goodbye]{std::cout << goodbye << '\n';}; 

// later 

say_hello(); // prints static string 
say_goodbye(); // prints string stored in the command 
+0

Zitat "Wenn Sie einen einfachen Funktionszeiger verwenden, benötigen Sie eine andere Funktion für alles, was Sie drucken möchten." Aber das musst du nicht. Sie können Funktionen mit verschiedenen Parametern aufrufen, wenn Sie einen Befehl mit verschiedenen Argumenten erstellen. – Narek

+3

@Narek, aber das Befehlsmuster lässt Sie keine Argumente angeben, wenn Sie den Befehl aufrufen, nur wenn Sie es erstellen. Sie brauchen also ein Objekt, um sie zu speichern, damit sie verfügbar sind, wenn sie aufgerufen wird. –

4

Befehlsmuster ist viel mehr als nur eine Funktion ausgeführt wird. Es kapselt Daten und Logik innerhalb einer Klasse und stellt ein Objekt bereit, das leicht als Parameter übergeben werden kann. Neben der Ausführung von Tasks kann es auch Ereignisse auslösen, Daten parsen und bereinigen und vieles mehr. Hier kommen Vererbungs- und Template-Methoden zum Einsatz, die Sie nicht mit Funktionszeigern erhalten. Die Implementierung von Undo und Redo ist sehr einfach mit Befehlen.

+0

+1 für Vererbung, Undo und Redo (mehrere Funktionen in Bezug auf den Befehl) und Einkapseln von Daten (d. H. Zustand) – Narek