Qualcuno può spiegare in parole povere?
I modelli di progettazione non sono in realtà concetti "laici", ma cercherò di renderlo il più chiaro possibile. Qualsiasi modello di progettazione può essere considerato in tre dimensioni:
- Il problema risolto dal modello;
- La struttura statica del modello (diagramma di classe);
- La dinamica del modello (diagrammi di sequenza).
Confrontiamo Stato e Strategia.
Problema risolto dal modello
Lo stato viene utilizzato in uno dei due casi [libro GoF p. 306] :
- Il comportamento di un oggetto dipende dal suo stato e deve cambiare il suo comportamento in fase di esecuzione a seconda di quello stato.
- Le operazioni hanno grandi istruzioni condizionali multipart che dipendono dallo stato dell'oggetto. Questo stato è generalmente rappresentato da una o più costanti enumerate. Spesso, diverse operazioni conterranno la stessa struttura condizionale. Il modello di stato mette ogni ramo del condizionale in una classe separata. Ciò consente di trattare lo stato dell'oggetto come un oggetto a sé stante che può variare indipendentemente dagli altri oggetti.
Se vuoi assicurarti di avere effettivamente il problema risolto dal modello di stato, dovresti essere in grado di modellare gli stati dell'oggetto usando una macchina a stati finiti . Puoi trovare un esempio applicato qui .
Ogni transizione di stato è un metodo nell'interfaccia di stato. Ciò implica che, per un progetto, devi essere abbastanza sicuro delle transizioni di stato prima di applicare questo modello. Altrimenti, se aggiungi o rimuovi transizioni, dovrai cambiare l'interfaccia e tutte le classi che la implementano.
Personalmente non ho trovato questo schema così utile. Puoi sempre implementare macchine a stati finiti usando una tabella di ricerca (non è un metodo OO, ma funziona abbastanza bene).
La strategia viene utilizzata per il seguente [libro GoF p. 316] :
- molte classi correlate differiscono solo nel loro comportamento. Le strategie forniscono un modo per configurare una classe con uno dei tanti comportamenti.
- hai bisogno di diverse varianti di un algoritmo. Ad esempio, è possibile definire algoritmi che riflettono diversi compromessi spazio / tempo. Le strategie possono essere utilizzate quando queste varianti sono implementate come una gerarchia di classi di algoritmi [HO87].
- un algoritmo utilizza dati che i clienti non dovrebbero conoscere. Utilizzare il modello di strategia per evitare di esporre strutture di dati complesse, specifiche dell'algoritmo.
- una classe definisce molti comportamenti e questi compaiono come più istruzioni condizionali nelle sue operazioni. Invece di molti condizionali, sposta i relativi rami condizionali nella propria classe Strategia.
L'ultimo caso di dove applicare la strategia è legato a un refactoring noto come Sostituisci condizionato con polimorfismo .
Riepilogo: Stato e strategia risolvono problemi molto diversi. Se il problema non può essere modellato con una macchina a stati finiti, probabilmente il modello di stato non è appropriato. Se il tuo problema non riguarda l'incapsulamento delle varianti di un algoritmo complesso, la Strategia non si applica.
Struttura statica del modello
State ha la seguente struttura di classe UML:
La strategia ha la seguente struttura di classe UML:
Riepilogo: in termini di struttura statica, questi due modelli sono per lo più identici. In effetti, strumenti di rilevamento dei modelli come questo ritengono che " la struttura dei [...] modelli è identica, vietandone la distinzione mediante un processo automatico (ad esempio, senza fare riferimento a informazioni concettuali) " .
Tuttavia, può esserci una grande differenza se ConcreteStates decide autonomamente le transizioni di stato (vedere le associazioni " potrebbero determinare " nel diagramma sopra). Ciò si traduce in accoppiamento tra stati concreti. Ad esempio (vedere la sezione successiva), lo stato A determina la transizione allo stato B. Se la classe Context decide la transizione allo stato concreto successivo, queste dipendenze scompaiono.
Dinamica del modello
Come menzionato nella sezione Problema sopra, lo stato implica che il comportamento cambia in fase di esecuzione in base a uno stato di un oggetto. Pertanto, la nozione di transizione di stato applica , come discusso con la relazione della macchina a stati finiti . [GoF] menziona che le transizioni possono essere definite nelle sottoclassi ConcreteState o in una posizione centralizzata (come una posizione basata su tabella).
Supponiamo che una semplice macchina a stati finiti:
Supponendo che le sottoclassi decidano la transizione di stato (restituendo il successivo oggetto di stato), la dinamica è simile a questa:
Per mostrare le dinamiche della strategia , è utile prendere in prestito un esempio reale .
Riepilogo : ogni modello utilizza una chiamata polimorfica per fare qualcosa a seconda del contesto. Nel modello di stato, la chiamata polimorfica (transizione) spesso provoca un cambiamento nello stato successivo . Nel modello di strategia, la chiamata polimorfica in genere non cambia il contesto (ad esempio, il pagamento con carta di credito una volta non implica che il pagamento verrà effettuato da PayPal la volta successiva). Ancora una volta, le dinamiche del modello statale sono determinate dalla relativa macchina a stati finiti, che (per me) è essenziale per la corretta applicazione di questo modello.