38.18. Lazy Materialization with a Virtual Proxy
It is sometimes desirable to defer the materialization of an object until it is absolutely required, usually for performance reasons. For example, suppose that ProductDescription objects reference a Manufacturer object, but only very rarely does it need to be materialized from the database. Only rare scenarios cause a request for manufacturer information, such as manufacturer rebate scenarios in which the company name and address are required.The deferred materialization of "children" objects is known as lazy materialization . Lazy materialization can be implemented using the Virtual Proxy GoF patternone of many variations of Proxy.A Virtual Proxy is a proxy for another object (the real subject ) that materializes the real subject when it is first referenced; therefore, it implements lazy materialization. It is a lightweight object that stands for a "real" object that may or may not be materialized.A concrete example of the Virtual Proxy pattern with ProductDescription and Manufacturer is shown in Figure 38.16. This design is based on the assumption that proxies know the OID of their real subject, and when materialization is required, the OID is used to help identify and retrieve the real subject.
Figure 38.16. Manufacturer Virtual Proxy.
[View full size image]
Who Creates the Virtual Proxy?
Observe in Figure 38.16 that the ManufacturerProxy collaborates with the PersistenceFacade in order to materialize its real subject. But who creates the ManufacturerProxy ? Answer: The database mapper class for ProductDescription . The mapper class is responsible for deciding, when it materializes an object, which of its "child" objects should also be eagerly materialized, and which should be lazily materialized with a proxy.Consider these alternative solutions: one uses eager materialization, the other lazy materialization.
Here is the lazy materialization solution:
// EAGER MATERIALIZATION OF MANUFACTURER
class ProductDescriptionRDBMapper extends AbstractPersistenceMapper
{
protected Object getObjectFromStorage( OID oid )
{
ResultSet rs =
RDBOperations.getInstance().getProductDescriptionData( oid );
ProductDescription ps = new ProductDescription();
ps.setPrice( rs.getDouble( "PRICE" ) );
// here's the essence of it
String manufacturerForeignKey = rs.getString( "MANU_OID" );
OID manuOID = new OID( manufacturerForeignKey );
ps.setManufacturer( (IManufacturer)
PersistenceFacade.getInstance().get(manuOID,Manufacturer.class);
...
}
// LAZY MATERIALIZATION OF MANUFACTURER
class ProductDescriptionRDBMapper extends AbstractPersistenceMapper
{
protected Object getObjectFromStorage( OID oid )
{
ResultSet rs =
RDBOperations.getInstance().getProductDescriptionData( oid );
ProductDescription ps = new ProductDescription();
ps.setPrice( rs.getDouble( "PRICE" ) );
// here's the essence of it
String manufacturerForeignKey = rs.getString( "MANU_OID" );
OID manuOID = new OID( manufacturerForeignKey );
ps.setManufacturer( new ManufacturerProxy( manuOID ) );
...
}
Implementation of a Virtual Proxy
The implementation of a Virtual Proxy varies by language. The details are outside the scope of this chapter, but here is a synopsis:
Language | Virtual Proxy Implementation |
---|---|
C++ | Define a templatized smart pointer class. No IManufacturer interface definition is actually needed. |
Java | The ManufacturerProxy class is implemented. The IManufacturer interface is defined.However, these are not normally manually coded. Rather, one creates a code generator that analyzes the subject classes (e.g., Manufacturer ) and generates IManufacturer and ProxyManufacturer .Another Java alternative is the Dynamic Proxy API. |
Smalltalk | Define a Virtual Morphing Proxy (or Ghost Proxy), which uses #doesNotUnderstand: and #become : to morph into the real subject. No IManufacturer definition is needed. |