Il prossimo problema da risolvere è fornire una logica più complessa per la determinazione del prezzo scontato di una vendita, per esempio con uno sconto in tutto il negozio per l'intera giornata, sconti per gli anziani e così via.
La strategia di determinazione del prezzo scontato per una vendita (una regola, una politica di sconto) può variare. Durante un periodo può essere pari al 10% di sconto su tutte le vendita, successivamente può essere uno sconto di 10 dollari se il totale della vendita è superiore a 200 dollari, e un infinità di altre varianti. Com'è possibile progettare questi algoritmi per il calcolo del prezzo scontato tenendo conto della loro variabilità?
La soluzione è Strategy.
Nome | Startegy |
---|---|
Problema | Come progettare per gestire un insieme di algoritmi o politiche variabili ma correlati? Come progettare per consentire la modifica di questi algoritmi o politiche? |
Soluzione | Definire ciascun algoritmo/politica/strategia in una classe separata, con un interfaccia comune. |
In genere, nel pattern strategy, gli algoritmi sono tutti correlati tra di loro, poiché risolvono lo stesso problema. Tale problema comune da risolvere è rappresentato dall'interfaccia comune, mentre i diversi algoritmi che risolvono il problema sono rappresentati dalle diverse classi che implementano quell'interfaccia comune. Per esempio, una classe per calcolare il prezzo di una vendita applicando uno sconto percentuale e un'altra classe per applicare uno sconto basato su una soglia.
Poiché il comportamento per la determinazione del prezzo scontato varia in base alla strategia, si creano diverse classi ISalePricingStrategy, ciascuna con un metodo polimorfo getTotal per il calcolo del totale della vendita con lo sconto applicato. Ciascun metodo getTotal prende come parametro una Sale, cosicché la strategia di determinazione del prezzo scontato possa reperire dalla Sale il prezzo prima dello sconto e poi applicare la regola di sconto. L'implementazione di ciascun metodo getTotal sarà diversa.
Tutte le classi che implementano ISaleStrategy devono definire getTotal e le classi rappresentano le varie strategie di sconto.
Nel pattern Strategy l'esecuzione di una strategia è basata su una collaborazione tra un oggetto strategia e un oggetto contesto.
L'oggetto contesto è l'oggetto a cui va applicato l'algoritmo.
L'oggetto contesto è associato ad un oggetto strategia.
Per esempio, quando il messaggio getTotal viene inviato a un Sale, per calcolare il totale scontato della vendita, essa delega una parte del lavoro al suo oggetto strategia. Si tratta di una prassi comune che il messaggio all'oggetto contesto e quello all'oggetto strategia abbiamo lo stesso nome, anche se non è obbligatorio (come si vede nel DSD sotto).
Inoltre è comune (e di fatto necessario) che l'oggetto contesto passi un riferimento a se stesso (this in java) all'oggetto strategia, in modo che la strategia abbia una visibilità per parametro nei confronti dell'oggetto contesto, per ulteriori collaborazioni. Infatti è comune che l'oggetto strategia usi o interroghi l'oggetto contesto. Per esempio, come si vede nella figura sopra, l'oggetto strategia PercentDiscountPricingStrategy invia all'oggetto Sale il messaggio getPreDiscountTotal per chiedergli il totale prima di applicare lo sconto.
Come per la ServicesFactory, essa può leggere da una proprietà di sistema (o da una sorgente di dati esterna) il nome della classe che deve essere usata per lo sconto in quel certo periodo.
Ci sono diversi algoritmi o strategie di determinazione del prezzo, che cambiano nel corso del tempo. Chi deve creare una strategia? Una buona scelta potrebbe essere di nuovo l'uso di una Factory: potrebbe per esempio esserci una Factory per le strategie richieste dall'applicazione. Si osservi che per avere una coesione bassa non può essere incaricata di creare le strategie la ServicesFactory.
La tipologia e/o la percentuale di sconto può variare nel tempo.
I valori delle percentuali di sconto che devono avere gli algoritmi di sconto saranno memorizzati in una sorgente di dati esterna, come una base di dati relazionale, ove possono essere facilmente modificati e applicati al sistema.