2014-04-08 7 views
6

Il modello di comando è per incapsulare i comandi negli oggetti. Ma perché non usare invece i puntatori di funzione. Perché devo sottoclasse la classe Command per ogni operazione? Invece posso avere diverse funzioni e chiamare quelle funzioni per memorizzare i puntatori e così via ...Motivo di comando: perché incapsulato in un oggetto

risposta

9

Ma perché non utilizzare invece i puntatori di funzione.

Perché i puntatori di funzione non possono memorizzare lo stato arbitrario. Spesso vorrete che il comando sia parametrizzato quando lo create. Per esempio:

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 

Se si sceglie di usare un puntatore a funzione semplice, allora avresti bisogno di una funzione diversa per tutto ciò che si potrebbe desiderare di stampare.

Perché ho bisogno di sottoclasse classe di comando per ogni operazione?

Perché è così che funziona l'OOP vecchia scuola; anche se, come accennato in precedenza, è possibile utilizzare il fatto che si tratta di un oggetto per parametrizzarlo invece di suddividerlo in sottoclasse.

Fortunatamente, moderno C++ ha strutture migliori:

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

Citazione "Se si dovesse utilizzare un puntatore a funzione semplice, sarà necessaria una funzione diversa per tutto ciò che si desidera stampare." Ma tu non devi. Puoi chiamare la funzione con diversi parametri, mentre crei un comando con argomenti diversi. – Narek

+3

@Narek ma il pattern Command non ti consente di fornire argomenti quando invochi il comando, solo quando lo crei. Quindi hai bisogno di un oggetto per archiviarli in modo che siano disponibili quando è invocato. –

4

modello di comando è molto più di una semplice esecuzione di una funzione. Incapsula dati e logica all'interno di una classe e fornisce un oggetto che può essere facilmente passato come parametro. Oltre ad eseguire attività, potrebbe anche generare eventi, analizzare e pulire i dati e molto altro, ed è qui che i metodi di ereditarietà e di template sono utili, che non si otterranno con i puntatori di funzione. Inoltre, implementare undo e redo è molto semplice usando i comandi.

+0

+1 per ereditarietà, annulla e ripristina (più funzioni correlate al comando) e incapsula i dati (ad esempio lo stato) – Narek

Problemi correlati