Command pattern: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
Nessun oggetto della modifica |
m →Altri progetti: Aggiunto il parametro "Preposizione" nel template "Interprogetto" |
||
(59 versioni intermedie di 41 utenti non mostrate) | |||
Riga 1:
Nella [[Programmazione orientata agli oggetti|programmazione a oggetti]], il '''Command pattern''' è uno dei pattern fondamentali, definiti originariamente dalla [[Gang of Four (scrittori)|Gang of Four]].
Il Command pattern è uno dei [[design pattern]] che permette di isolare la porzione di codice che effettua un'azione (eventualmente molto complessa) dal codice che ne richiede l'esecuzione; l'azione è incapsulata nell'oggetto Command.
L'obiettivo è rendere variabile l'azione del client senza però conoscere i dettagli dell'operazione stessa. Altro aspetto importante è che il destinatario della richiesta può non essere deciso staticamente all'atto dell'istanziazione del command ma ricavato a tempo di esecuzione.
== Struttura ==
[[ == Esempio ==
In un modulo (python) è definita la classe che segue.
<syntaxhighlight lang=python>
class RoomHandler:
...
</syntaxhighlight>
Questa è destinata a occuparsi della gestione delle camere di una casa nonché, attualmente, allo svolgimento di alcuni lavori da eseguire.
Sono infatti definite alcune sottoclassi che implementano diversi lavori che è possibile svolgere sulle pareti delle camere.
<syntaxhighlight lang=python>
class Painter(RoomHandler)
...
def actionWork(self, arguments):
""" paint some walls """
...
class PaperGluer(RoomHandler)
...
def actionWork(self, arguments):
""" glue wallpaper to some walls """
...
class ShelfMounter(RoomHandler)
...
def actionWork(self, arguments):
""" mount shelves to some walls """
</syntaxhighlight>
Questo approccio presenta diversi aspetti negativi.
# A fronte di ''n'' possibili lavori (azioni) si rendono necessarie diverse sottoclassi: una per ciascuna azione da implementare e una per ogni possibile composizione di azioni base (per esempio dipingere camera e montare di seguito gli scaffali). Qualora invece le azioni fossero ''Command'' indipendenti dal RoomHandler, sarebbe possibile creare istanze su quest'ultimo piuttosto che creare sottoclassi.
# ''RoomHandler'' contiene sia il codice di gestione delle camere che il codice che esegue le azioni: esso è sovraccarico di responsabilità ed estendere un'azione comporta un aumento della complessità del ''RoomHandler''.
# Testare oggetti con numerose responsabilità è in genere complesso e oneroso. Incapsulare le azioni in ''Command'' rende possibile il testing esclusivo su ciascuna azione (eventualmente ricorrendo all'uso di [[Mock Objects|Mock]]) il che semplifica notevolmente la fase di testing e validazione.
Segue il codice equivalente strutturato seguendo le indicazioni del pattern:
<syntaxhighlight lang=python>
class Command:
def execute(self):
raise NotImplementedError
class PaintWallCommand(Command)
def execute(self, wall):
""" paint a wall """
class GlueWallPaperCommand(Command)
def execute(self, wall):
""" glue wall paper to a wall """
class MountShelfCommand(Command)
def execute(self, wall):
""" mount shelf to a wall """
</syntaxhighlight>
Sia nell'atto di creazione di un'istanza ''RoomHandler'', sia a ''run-time'', è possibile selezionare le azioni che si intende svolgere:
<syntaxhighlight lang=python>
def createRoomHandler(self):
handler = RoomHandler()
handler.addWork(PaintWallCommand())
handler.addWork(MountShelfCommand())
class RoomHandler(self)
...
def actionWork(self):
for work in self.getWorks():
work.execute(self.getSelectedWall())
</syntaxhighlight>
== Considerazioni ==
# L'oggetto dell'operazione (nell'esempio la parete) non è deciso al momento della creazione delle azioni ma a tempo di esecuzione.
# È possibile incapsulare un'azione in modo che questa sia atomica. È così possibile implementare un paradigma basato su transazioni in cui un insieme di operazioni è svolto in toto o per nulla.
# I ''Command'', i quali sono a conoscenza delle operazioni che sono chiamati a svolgere, possono implementare funzioni di ''unexecute'' o ''undo''. In casi come questi, il Command può memorizzare lo stato precedente alla sua esecuzione, ripristinandolo qualora l'operazione debba essere annullata.
# È possibile rendere asincrona la scelta dei comandi rispetto alla loro esecuzione. Un certo numero di command possono essere ''consumati'' da un altro oggetto che li riceve in un tempo diverso dalla loro selezione.
== Bibliografia ==
* [[Erich Gamma|Gamma, E.]], [[Richard Helm|Helm, R.]], [[Ralph Johnson (informatico)|Johnson, R.]] e [[John Vlissides|Vlissides, J.]], '' [[Design Patterns]]: elementi per il riuso di software a oggetti'', Addison Wesley, 1995, ISBN 88-7192-150-X.
** Originale: ''Design Patterns: Elements of Reusable Object-Oriented Software'', Addison Wesley, 1995, ISBN 0-201-63361-2.
== Altri progetti ==
{{interprogetto|preposizione=sul}}
{{Design pattern}}
{{Portale|informatica}}
[[Categoria:Design pattern]]
|