|
Introduzione
II componenti di business (business objects - BO) espongono
i loro servizi mediante le relative interfacce. Un business
tier formato da piu' BO comporta :
-
forte accoppiamento (tight coupling) tra client e
i BO
- accesso
complesso e non uniforme alle risorse di business
- problemi
di performance sulla rete a causa delle complesse
e numerose interazioni
client - BO
A cosa serve questo pattern
L'intento del pattern Facade è di :
- esporre
un'interfaccia "a grana grossa"(coarse-grained)
unificata e omogenea (e quindi semplificata) del business
tier
- ridurre
il numero di BO esposti al client
- ridurre
l'accoppiamento tra client e BO
- migliorare
le performance di rete diminuendo le interazioni remote
tra client e BO
- astrarre
il client dai dettagli implementativi di business
- nascondere
la complessità delle interazioni e delle dipendenze
dei BO
- concentrare
il security management ed il transaction management
sul business tier
Questo
si ottiene anteponendo ai BO un EJB di tipo Session
il cui compito è interfacciare e gestire i singoli
componenti di business.
Nei
Sequence Diagram riportati si illustrano le interazioni
fra un client e i BO senza una classe Facade:

e
con l'utilizzo di una classe Facade :

Motivazione
Il pattern individua nel Session Facade il "Controller"
del business tier con il compito di coordinare e gestire
le interazioni fra i BO: il Facade diventa il punto
ottimale dove gestire il "workflow" di business
(interazioni tra BO, gestione delle transazioni, controllo
validità dati,
).
Spiegazione del funzionamento
Il Facade disaccoppia il client dalla complessità
del business tier esponendone un'interfaccia uniforme.
A
titolo di esempio si riporta il codice di un client
che accede a due diversi EJB:
Context
ctx = null;
ctx = new InitialContext();
Object obj = ctx.lookup(JndiNames.ACCOUNT);
AccountHome accountHome = (AccountHome)PortableRemoteObject.narrow(
obj,
AccountHome.class);
// find the account
Account account = accountHome.findByPrimaryKey(new AccountPK(userid));
obj = ctx.lookup(JndiNames.SHOPPER);
ShopperHome shopperHome=(ShopperHome)PortableRemoteObject.narrow(
obj,ShopperHome.class);
// Create the eCommerce basket
Shopper shopper = shopperHome.create(userid);
double balance = account.getBalance();
shopper.addItem(new ProductOM(. . .));
if(shopper.getAmount() > account.getBalance())
System.out.println("Acquisto
# NON # possibile !");
else
System.out.println("Acquisto
possibile.");
A
parità di funzionalità offerte, l'utilizzo
del pattern Facade semplifica il codice del client come
mostrato di seguito :
try
{
Context ctx = null;
ctx = new InitialContext();
// Lookup del Façade che gestisce
gli EJB Account e Shopper
Object obj = ctx.lookup(JndiNames.FACADE);
FacadeHome facadeHome = (FacadeHome)PortableRemoteObject.narrow(
obj,
FacadeHome.class);
Facade facade = facadeHome.create(userid);
facade.addItem(new ProductOM(. . .));
System.out.println("Acquisto possibile.");
}
catch(BuyException be) {
System.out.println("Acquisto # NON
# possibile !");
}
Struttura
Il Facade

Class
Diagram

Sequence
Diagram
A secondo dello scopo del Facade, l'implementazione
può variare dal "semplice passa carte"
(delega ai BO la logica di business) al realizzare le
regole di business (coordinando i BO necessari).
L'EJB Facade può essere sia di tipo Stateful
che Stateless, a secondo della necessità di contenere
o meno una stato conversazionale.
Quando si procede all'implementazione di un Facade,
è bene tenere presente la granularità
che il componente offre al client.
La letteratura indica di non associare un Facade ad
ogni singolo use case (grana toppo fine) bensì
ad un insieme di use case correlati ottenendo una granularità
"piu' grossa".
Di
seguito si riporta un esempio di implementazione di
un Session Facade di tipo stateful :
public
class FacadeBean implements SessionBean {
/** Reference to the Shopper Stateful EJB */
private Shopper shopper = null;
/** Reference to the Account Entity EJB entity bean
*/
protected Account account = null;
Nel
metodo ejbCreate si crea un Ejb stateful per la gestione
del carrello della spesa (Shopper) e un Entity per la
gestione del conto virtuale dell'utente (Account).
public void ejbCreate(String ID) {
try {
Context ctx = new InitialContext();
Object lookupObject = ctx.lookup(<<JNDI_NAME_SHOPPER>>);
ShopperHome shopperHome =(ShopperHomePortableRemoteObject.narrow(
lookupObject,ShopperHome.class);
lookupObject = ctx.lookup(<<JNDI_NAME_SHOPPER>>);
AccountHome accountHome = (AccountHome)
PortableRemoteObject.narrow(lookupObject,
AccountHome.class);
this.shopper = shopperHome.create(ID);
this.account = accountHome.findByPrimaryKey(new
AccountPK(ID));
A
titolo di esempio si mostrano tre possibili implementazioni
dei metodi del Facade :
- removeItem:
il Facade delega l'operazione all'EJB Shopper
- addItem:
il Facade implementa la logica di business utilizzando
sia dati dell'EJB Shopper che i business data dell'EJB
Account
- deposit:
il Facade implementa le business rules e solo nel
caso che siano soddisfatte provvede ad accedere ai
business data
public
void removeItem(ProductOM prod)throws BusinessException{
try{
shopper.removeItem(prod);
}
catch(RemoteException re) {
throw new BusinessException(re);
}
}
public void addItem(ProductOM prod) throws BusinessException{
try{
// somma tra il costo del prodotto
e l'attuale ammontare
// della spesa
double totToPay = prod.getPrice()+
shopper.getAmount();
// se il totale è inferiore
dei soldi disponibili
// aggiungo il prodotto al carrello
della spesa
if( totToPay > account.getBalance())
throw new BusinessException(.
. .);
shopper.addItem(prod);
}
catch(RemoteException e) {
throw new BusinessException(e);
}
}
public void deposit(double money) throws BankException
{
try {
if ((money <= 0)||(money
> <<MAX VALUE>>))
throw new BankException("Deposit
["+money+"] NOT allowed !");
// aggiorno il saldo se la cifra
è compresa
// nel range specificato
account.setBalance(account.getBalance()
+ money);
} catch (RemoteException e) {
throw new BankException(e);
}
}
Un
caso d'uso
Nell'esempio proposto il Session Facade gestisce un
semplice caso di eCommerce "nascondendo" al
client la gestione degli EJB Shopper e Account.

Bibliografia
e riferimenti
L'archivio zip con gli esempi è scaricabile qui.
[Gof] Gamma, Helm, Johnson, Vlissides :
Design Patterns - Elements of Reusable Object-Oriented
Software
[J2EE]
Alur,Crupi,Malks :
Core J2EE Patterns - Best Practices and Design Strategies
[SJP]
Sun Java Center J2EE Patterns:
http://developer.java.sun.com/developer/restricted/patterns/J2EEPatternsAtAGlance.html
[BPP]
Sun blueprints-Design Patterns Catalog : http://java.sun.com/blueprints/patterns/j2ee_patterns/catalog.html
[EJBA]
G.Puliti- Corso di EJB VI parte : un esempio completo,
Mokabyte N.51, Aprile 2001
|