MokaByte 69 - Dicembre 2002 
Il Pattern Value Object
di

S. Rossini
L. Dozio

Contesto
Le applicazioni client necessitano scambio di dati con i business objects.

A cosa serve
L'intento del pattern è di modellare i dati di business in modo granulare mediante oggetti: i ValueObject. I Value Object incapsulano la quantità di business data necessaria per soddisfare le esigenze del client nel colloquio con l'EJB.
In questo modo si ottiene una visione ad oggetti dei dati di business ottimizzando il trasferimento remoto dei dati.

 

Motivazione
Come ogni pattern ci sono diverse strategie:

  • Oggetti immutabili (i suoi campi sono solo read-only, cioè solo metodi get) - Value Objects Strategy
  • Business objects che rappresentano strutture dati (metodi get/set) - Updatable Value Objects Strategy
  • Aggregazione di diversi oggetti immutabili - Multiple Value Object Strategy
  • Aggregazione di oggetti immutabili reperiti da differenti data store - Value Object Assembler Strategy
    Spiegazione del funzionamento
    Si crea e si utilizza un Ejb, sul quale vengono invocati i metodi per reperire i dati di business.

public class FacadeTestClient {
. . .
public void test(String userid) {
Context ctx = new InitialContext();
Object obj = ctx.lookup(JndiNames.FACADE);
FacadeHome facadeHome = (FacadeHome)PortableRemoteObject.narrow(obj, FacadeHome.class);
Facade facade = facadeHome.create(userid);
System.out.println("User account name : " + facade.getName());
System.out.println("User account email : " + facade.getEmail());
System.out.println("User account balance : " + facade.getBalance());

A parità di funzionalità offerte, l'utilizzo del pattern Value Object richiede una sola invocazione remota all'EJB:

public class FacadeObjectValueTestClient {
. . .
public void test(String userid) {
Context ctx = new InitialContext();
Object obj = ctx.lookup(JndiNames.FACADE);
FacadeHome facadeHome = (FacadeHome)PortableRemoteObject.narrow(obj, FacadeHome.class);
Facade facade = facadeHome.create(userid);
AccountVO objectValue = facade.getAccount();
System.out.println("User account name : " + objectValue.getName());
System.out.println("User account email : " + objectValue.getEmail());
System.out.println("User account balance : " + objectValue.getBalance());

Usando accorgimenti di programmazione come il Value Object si ottimizza il trasferimento delle informazioni al client evitando di fare viaggiare singolarmente i dati applicativi (nell'esempio sono i dati name, email e balance).



Figura 1 - Funzionamento senza ValueObject

 


Figura 2 - Funzionamento con ValueObject

 

Struttura


Figura 3 -
Class Diagram

Un caso d'uso
L'EJB Facade presentato in [FACADE] piuttosto che restituire i singoli dati dell'Entity Bean Account

public class FacadeBean implements SessionBean {

// Remote reference to the Entity EJB Account
private Account account = null;
. . .
// <<property name>> è il nome della
// proprietà dell'Entity EJB (name, email, balance)
public double get<<property name>> () {
  try {
    return account.get<<property name>>();
  } catch (java.rmi.RemoteException e) {
    throw new BusinessException("Exception reading property                                  <<property name>> : " + e);
  }
}

mette a disposizione un metodo di business che crea un Value Object, lo popola "accorpando" i dati prelevati dall'Entity e lo restituisce:

public class FacadeBean implements SessionBean {

  // Remote reference to the Entity EJB Account
  private Account account = null;
  ...
  public AccountVO getAccount() throws BusinessException {
    try{
        AccountVO objectValue;
        objectValue = new AccountVO(this.account.getName(),
                                    this.account.getEmail(),
                                    this.account.getBalance());
        return objectValue;
    } catch (java.rmi.RemoteException e) {
      throw new BusinessException("FacadeBean getBalance()
                                   failed: " + e);
    }
}

Il Value Object è costituito dalla classe AccountVO, che è una classe Java serializzabile con gli opportuni metodi get:

public class AccountVO implements java.io.Serializable{

private String name=null;
private String address=null;
private double balance= 0.0;
public AccountVO(String nm, String add, double bal) {
  this.name = nm;
  this.address = add;
  this.balance = bal;
}

  // Accessors
  public String getName(){return this.name;}
  public String getAddress(){return this.address;}
  public double getBalance(){this.balance; }
}

Il trasferimento dati tra l'EJB Facade e l'Entity Account può essere ulteriormente ottimizzato applicando nuovamente il pattern Value Object analogamente a quanto fatto per la comunicazione tra client e EJB Facade. L'Entity Account espone un nuovo metodo getAccount() che restituisce un Value Object AccountVO.

public class AccountBean implements EntityBean {
  private double balance;
  private String name;
  private String email;
  ...
  public AccountVO getAccount() {
    AccountVO objectValue = new AccountVO(id,     this.name,this.email,this.balance);
    return objectValue;
  }
...
}

In questo modo il Facade EJB non invoca piu' i metodi getName(), getEmail() e getBalance(), bensì il solo metodo getAccount():

public class FacadeBean implements SessionBean {
private Account account = null;
. . .
public AccountVO getAccount() throws BusinessException {
try{
return this.account.getAccount();
. . .

<<INSERIRE QUI IMMAGINE 4>>


Risorse
L'esempio è scaricabile qui

 

Bibliografia e riferimenti
[FACADE] S.Rossini, L. Dozio - "J2EE Patterns - Il pattern facade", Mokabyte N.64 Giugno
[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

 
MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it