So che questa è una vecchia domanda, ma penso di avere un altro esempio interessante che ho implementato di recente.
Questo è un esempio molto pratico del modello di strategia utilizzato in un sistema di consegna dei documenti.
Avevo un sistema di consegna PDF che riceveva un archivio contenente molti documenti e alcuni metadati. Sulla base dei metadati, ha deciso dove inserire il documento; per esempio, a seconda dei dati, ho potuto conservare il documento in A
, B
o C
sistemi di storage, o una combinazione dei tre.
Diversi clienti utilizzavano questo sistema e avevano diversi requisiti di rollback / gestione degli errori in caso di errori: uno voleva che il sistema di consegna si fermasse al primo errore, lasciasse tutti i documenti già consegnati nei loro magazzini, ma interrompesse il processo e non consegnasse altro ; un altro voleva che venisse eseguito il rollback B
in caso di errori durante l'archiviazione C
, ma lasciare tutto ciò che era già stato consegnato a A
. È facile immaginare che anche un terzo o un quarto avrà esigenze diverse.
Per risolvere il problema, ho creato una classe di consegna di base che contiene la logica di consegna, oltre a metodi per ripristinare le cose da tutti gli archivi. Questi metodi non vengono effettivamente chiamati direttamente dal sistema di consegna in caso di errori. Invece, la classe utilizza Dependency Injection per ricevere una classe "Rollback / Error Handling Strategy" (basata sul cliente che utilizza il sistema), che viene chiamata in caso di errori, che a sua volta chiama i metodi di rollback se è appropriato per quella strategia.
La stessa classe di consegna segnala cosa sta succedendo alla classe di strategia (quali documenti sono stati consegnati a quali archivi e quali errori si sono verificati) e ogni volta che si verifica un errore, chiede alla strategia se continuare o meno. Se la strategia dice "stop it", la classe chiama il metodo "cleanUp" della strategia, che utilizza le informazioni precedentemente riportate per decidere quali metodi di rollback chiamare dalla classe di consegna, o semplicemente non fare nulla.
rollbackStrategy.reportSuccessA(...);
rollbackStrategy.reportFailureB(...);
if (rollbackStrategy.mustAbort()) {
rollbackStrategy.rollback(); // rollback whatever is needed based on reports
return false;
}
Quindi ora ho due diverse strategie: una è la QuitterStrategy
(che si chiude al primo errore e non ripulisce nulla) e l'altra è la MaximizeDeliveryToAStrategy
(che cerca il più possibile di non interrompere il processo e non ripristinare mai le cose consegnate in archivio A
, ma esegue il rollback delle cose da B
se la consegna a C
non riesce).
A quanto mi risulta, questo è un esempio del modello strategico. Se tu (sì, stai leggendo) pensi che mi sbagli, per favore commenta qui sotto e fammi sapere. Sono curioso di sapere cosa costituirebbe un uso "puro" del modello di strategia e quali aspetti della mia implementazione violano la definizione. Penso che sia un po 'divertente perché l'interfaccia strategica è un po' grassa. Tutti gli esempi che ho visto finora utilizzano un solo metodo, ma penso ancora che questo incapsuli un algoritmo (se un pezzo di logica aziendale può essere considerato un algoritmo, cosa che penso lo faccia).
Poiché la strategia viene notificata anche sugli eventi durante l'esecuzione della consegna, può anche essere considerata un osservatore , ma questa è un'altra storia.
Da una piccola ricerca, sembra che questo sia un "pattern composito" (come MVC, un pattern che utilizza più pattern di progettazione sottostanti in un modo particolare) chiamato Advisor . È un consigliere sul fatto che la consegna debba continuare o meno, ma è anche un gestore di errori attivo poiché può eseguire il rollback di cose quando richiesto.
Ad ogni modo, questo è un esempio piuttosto complesso che potrebbe farti sentire che gli usi del modello strategico sono fin troppo semplici / sciocchi. Può essere davvero complesso e persino più applicabile se usato insieme ad altri modelli.