Should strategy objects have state?
Il libro Gang of Four Design Patterns ha alcune cose da dire sullo stato contenuto nel modello di strategia.
Ci sono due metodi descritti per contenere lo stato:
- Fornire alla strategia qualsiasi informazione di stato di cui ha bisogno. L'interfaccia definisce vari metodi e i parametri necessari affinché la strategia possa svolgere il suo compito.
- Consenti al contesto di fornire se stesso alla Strategia, sia alla creazione della Strategia sia quando viene eseguita la Strategia. La strategia può accedere solo ai dati necessari attraverso l'interfaccia specificata.
La prima opzione porta a una strategia e un contesto disaccoppiati. La seconda opzione porta ad un accoppiamento più stretto tra la strategia e il contesto. Potresti considerare il fattore di accoppiamento / coesione quando scegli un'implementazione della strategia.
Strategies increase the number of objects in an application. Sometimes you can reduce this overhead by implementing strategies as stateless objects that contexts can share. Any residual state is maintained by the context, which passes it in each request to the Strategy object. Shared strategies should not maintain state across invocations. The Flyweight (195) pattern describes this approach in more detail.
Ciò che questo dice è che, tipicamente, lo stato necessario per attuare la strategia viene mantenuto nel contesto. Ciò consente di condividere le strategie tra i vari contesti senza preoccuparsi di contenere uno stato non valido. Finché il contesto ha uno stato valido, sarà garantito che lo stato valido sarà gestito dalla Strategia poiché viene fornito secondo necessità.
What's a good approach in this situation?
Nella tua situazione, prenderei in considerazione di non archiviare queste informazioni nella Strategia. Non ha nulla a che fare con l'esecuzione, ma piuttosto il risultato dell'algoritmo di validazione.
Se hai bisogno di mantenere i dati su successo / fallimento, ci sono più punti di errore, e non fermi l'algoritmo dopo il primo errore, prenderei in considerazione la seconda implementazione che ho descritto sopra, dove passi il Contesto nella strategia. Usando un callback, il Contesto mantiene una collezione di errori di validazione. Ogni volta che una strategia incontra un errore, chiama semplicemente un metodo specificato nel contesto per aggiungere informazioni.
...it might need to perform two validations simultaneously...
Per questo motivo, il mio approccio consisterebbe in una struttura di dati come una mappa nel contesto. La mappa sarebbe una mappatura tra strategia e errore di convalida, o forse una mappa tra la strategia e una raccolta di errori di convalida.