Nella programmazione a oggetti, il Command pattern è uno dei pattern fondamentali, definiti originariamente dalla 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.
In un modulo (python) è definita la classe che segue.
class RoomHandler:
...
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.
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 """
Questo approccio presenta diversi aspetti negativi.
Segue il codice equivalente strutturato seguendo le indicazioni del pattern:
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 """
Sia nell'atto di creazione di un'istanza RoomHandler, sia a run-time, è possibile selezionare le azioni che si intende svolgere:
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())