Facade

Il sistema POS deve prevedere che esso sia lievemente modificabile, ovvero che consenta ai compratori di inserire regole di business personalizzabili.

Per essere più precisi, per esempio:

  • si supponga che, quando viene creata una nuova vendita, sia possibile identificare che questa sarà pagata con un "buono regalo". Un negozio potrebbe avere un regola per consentire l'acquisto di un solo articolo nel caso in cui venga utilizzato un buono regalo. Di conseguenza, le operazioni enterItem successive alla prima devono essere invalidate.
  • Inoltre, se la vendita viene pagata tramite un buono regalo, si devono invalidare tutti i tipi di restituzione del resto al cliente (al massimo sotto-forma di un nuovo buono regalo). Il resto mediante contanti deve essere invalidato.
  • Si supponga poi che, quando viene creata un nuova vendita, sia possibile identificare che venga devoluta a una causa di beneficenza. Un negozio potrebbe anche avere una regole che consente solo l'inserimento di articoli il cui prezzo è inferiore a 250 dollari, e che consente l'aggiunta degli articoli alla vendita solo se il "cassiere" autenticato è un direttore.

In termini di analisi dei requisiti, occorre identificare i punti specifici negli scenari di tutti i casi d'uso. Per questa investigazione verrà considerato solo il punto enterItem, ma la stessa soluzione si applica nello stesso modo a tutti i punti.
Si supponga inoltre che l'architetto non sia sicuro dell'implementazione migliore per questa gestione delle regole inseribili, e voglia sperimentare diverse soluzioni per rappresentare, caricare e valutare le regole. Per esempio, le regole possono essere implementate con il pattern Strategy, o con un interprete di regole open source che legga e interpreti un insieme di regole IF-THEN, o con un interprete di regole commerciale, da acquistare, o con un sistema per la gestione di regole (gratuito o commerciale).

Per risolvere questo problema di progettazione è possibile utilizzare il pattern strutturale Facade.

NomeFacade
ProblemaÉ richiesta un'interfaccia comune e unificata per un insieme disparato di implementazioni o interfacce, come per definire un sotto-sistema. Può verificarsi un accoppiamento indesiderato a molti oggetti nel sotto-sistema, oppure l'implementazione del sotto-sistema può cambiare. Che cosa fare?
SoluzioneDefinire un punto di contatto singolo con il sotto-sistema, ovvero un oggetto facade (facciata) che copre il sotto-sistema. Questo oggetto presenta una interfaccia singola e unificata ed è responsabile della collaborazione con i componenti del sotto-sistema.

Una Facade è un oggetto "front-end" che rappresenta il punto di entrata singolo ai servizi di un sotto-sistema; l'implementazione e gli altri componenti del sotto-sistema sono privati e non possono esser visti dai componenti esterni. Una Facade fornisce Protected Variations da cambiamenti nell'implementazione di un sotto-sistema.

Per esempio verrà fornito un sotto-sistema "motore delle regole", la cui implementazione specifica non è ancora nota. L'oggetto Facade per questo sotto-sistema sarà chiamato POSRuleEngineFacade. Il progettista decide di collocare le chiamate alla Facade vicino all'inizio dei metodi che sono stati definiti come punti per regole inseribili, come nel seguente esempio:
Pasted image 20230626183915.png

public class Sale{
	public void makeLineItem(ProductDescription desc, int quantity){
		SaleLineItema sli = new SaleLineItem(desc, quantity);
		// chiamata alla Facade
		if(POSRuleEngineFaced.getInstance().isInvalid(sli, this)){
			return;
		}
		// se invece la regola è soddisfatta
		lineItems.add(sli);
	}
	//...
}

Si noti l'uso del pattern Singleton. Spesso agli oggetti Facade vi si accede tramite Singleton.
Con questo progetto, la complessità e l'implementazione di come verranno rappresentate e valutate le regole sono nascoste nel sotto-sistema "motore delle regole", a cui si accede attraverso l'oggetto Facade POSRuleEngineFacade. Si osservi che il sotto-sistema nascosto dall'oggetto Facade potrebbe contenere decine o centinaia di classi oggetti, o addirittura una soluzione non orientata agli oggetti. Tuttavia, un client del sotto-sistema vede solo il suo punto di accesso pubblico unico.

Inoltre è stata ottenuta, una separazione degli interessi: tutte le problematiche di gestione delle regole sono state delegate a un altro sotto-sistema.

Per un migliore comprensione
...

Immaginiamo una classe client, che per effettuare una operazione deve accedere a diversi oggetti, magari molto eterogenei tra di loro:
Pasted image 20230626190222.png
allora, per rendere più semplice al client tale accesso viene utilizzata una classe Facade, posta tra gli oggetti e il client. La Facade sarà l'unico punto di accesso per il client, gli oggetti sottostanti gli verranno nascosti e gli sarà semplificata l'operazione da effettuare:
Pasted image 20230626190348.png

Come esempio, immaginiamo un utente che deve interagire con un computer, ma non sa come mettere insieme tutti i pensi per poter far funzione il computer e interagire con esso.
Allora abbiamo, le parti complesse del computer:
Pasted image 20230626190436.png
E la Facade che mette insieme tutto (effettuando le operazioni complesse che servono per mettere insieme un computer e per accenderlo):
Pasted image 20230626190519.png
A questo punto l'utente (il client) può interagire solo con la Facade e avviare in maniera del tutto semplificata il computer (senza tenere conto di ciò che vi è al di sotto).
Pasted image 20230626190654.png