Package com.thoughtworks.proxy.toys.delegate

A toy to delegate method calls to another object.

See:
          Description

Class Summary
Delegating<T> Toy factory to create proxies delegating to another object.
Delegating.DelegatingBuild<T>  
Delegating.DelegatingModeOrBuild<T>  
Delegating.DelegatingWith<T>  
DelegatingInvoker<T> Invoker that delegates method calls to an object.
 

Enum Summary
DelegationMode Indicates the preferred way to delegate to created proxies.
 

Exception Summary
DelegationException Exception thrown if a delegation from the proxy to the delegated object fails.
 

Package com.thoughtworks.proxy.toys.delegate Description

A toy to delegate method calls to another object.

The package provides a proxy factory creating proxies, that are used to delegate method calls to another object. Main component is the Delegate toy, a utility class creating these proxies. Such a proxy contains an instance of a DelegatingInvoker that routes all calls. The DelegatingInvoker may either call the method directly for the delegated object, that was originally called for the proxy, or it may lookup a method with the same name at the delegated object, that has the called method's signature. The second approach allows an implicit implementation of an interface, if the delegated object has API compatible methods, but does not implement the interface. This approach is always taken from this toy factory.

The following example makes a ThreadLocal instance compatible with an ObjectReference found in the ProxyToys' kit:

ThreadLocal<Boolean> threadLocal = new ThreadLocal<Boolean>() {
    @Override
    protected Boolean initialValue() {
        return Boolean.TRUE;
    }
};
@SuppressWarnings("unchecked")
ObjectReference<Boolean> ref = Delegating.proxy(ObjectReference.class)
    .with(threadLocal)
    .build();
System.out.println("This ObjectReference has an initial value of <" + ref.get() + ">");

The use case for this example is to hide the implementation details completely from the user. We want to provide the user with a DataInput, that is internally implemented using a RandomAccessFile. Unfortunately this class implements DataInput as well as DataOutput and a user might just cast the returned object and violate the contract. We use a delegating proxy to prevent this:

public DataInput getDataInput(File f) throws IOException {
    RandomAccessFile raf = new RandomAccessFile(f, "rw");
    raf.writeBytes("Content");
    raf.seek(0);
    return Delegating.proxy(DataInput.class)
        .with(raf)
        .mode(DelegationMode.DIRECT)
        .build();
}

The returned DataInput cannot be casted to a DataOutput anymore. In this case we used the first approach, since the proxied object implements the interface and the methods can be called directly.



Copyright © 2005-2010 Codehaus. All Rights Reserved.