Proxy Pattern:
Well,according to Wikipedia:
A class functioning as an interface to another thing.The other thing could be anything.a network connection,a large object in memory,a file or some resource that is expensive/impossible to duplicate.
Intent:-> Provide a placeHolder for another object to control access to it.
-> Use an extra level of indirection to support distributed,controlled or intelligent access.
-> Add a wrapper and delegation to protect the real component from undue complexity.
Motivation:
-> Has the same interface as the target object.
-> Holds a reference to the target object and can forward requests to the target as required.(Delegation)
Problem: We need to support resource-hungry objects,and we donot want to instantiate such objects unless and until they are actually requested by the client.
Example: The proxy provides a surrogate or place holder to provide to an object.A check or bank draft is a proxy for funds in an account.A check can be used in place of cash for making purchases and untimately controls access to cash in the issuer's acccount.[Michael Duell, "Non-software examples of software design patterns", Object Magazine, Jul 97, p54]
Remember-> Adapter provides a diff interface to the subject.Proxy provides the same interface.Decorator provides an enhanced interface[GoF. p216].Decorator pattern constructs object at runtime by recursively enclosing an object with one or more decorators.Proxy Pattern acts as a stand-in for a real subject which is set at compile time.
Types of Proxy:
Remote Proxy: Provides a reference to an object located in different address space on the same or diff machine.
Virtual Proxy: Allows the creation of memory intensive object on demand.So the object will not be created until it is really needed.
Copy-On-Write proxy: Defers copying(cloning) a target object until required on client actions.This is a special case of Virtual proxy.
Protection(access) proxy: Provides diff clients with diff levels of access to the target object.
Cache Proxy: Provides temporary storage of results of expensive target operations so that clients can share the result.
Firewall Proxy: Protects targets from bad clients(or vice-versa)
Synchronization Proxy: provides concurrency control over an unsynchronized target object.
Smart Reference Proxy: Provides additional actions whenever a target object is referenced,such as counting the number of references to the object.
However Gang of Four book refers only 4 types of proxy pattern
a)Virtual proxies
b) Remote proxy
c) Protection proxies
d) Smart references
You may remember that it provides an alternative to extending functionality with inheritance.That alternative is object composition,where an object(proxy) forwards method calls to the enclosed object(real subject)
Object composition is surely preferred to inheritance for the sole reason that it hides the internals.By inheritance we get access to all public/protected resources in sub classes where as by object composition we may not have the luxury.
Intercepter Pattern:
Problem:-> How can we allow others to monitor what goes on inside it.
-> Optionally change extend the behavior
-> Without making them understand/Change our code.
-> Without affecting our system.
Definition: An interceptor is a method that intercepts a business method invocation.
Possible locations:
-> Enterprise Bean Class
-> seperate intercepter class
They can be used to
-> Modify parameters before they are passed to the bean.
-> Modify the value returned from the bean.
-> catch and handle method exceptions
-> interruprt call,provide logging and many more.
Advantages:
-> Extensibility and Flexibility
-> Seperation of Concerns
-> Allows monitoring and control of systems
-> Promotes resusability
Disadvantags:-> Security
-> Possibility for infinite invocation etc
Now we will see one example where we can combine nicely Proxy and Intercepter Pattern.
Well purpose of using proxy pattern is to have control of the creation process of remote objects.And purpose of using intercepter pattern is to provide logging for each request to our ejb methods like whenever any method is requested we provide by initiate some audting and similarly whenever any method is exited we do the same.Please remember that intercepters are created once per JVM hence stateless.Also we need to take care of intercepters as it may disrupt the main method call.
Step 1: Define intercepter interface(We want it to be invoked before our main method call get's called and also after main method call terminates.)
public interface Interceptor {
public void doBeforeCall(final Method method, final Object[] argv); ///Before target call.
public void doAfterCall(final Method method, final Object[] argv,final Object result); // after target call
}
STEP 2: Define Delegate class which will act as Proxy class and also implements InvocationHandler
public abstract class Delegate implements InvocationHandler {
public static Object newProxyInstance(Class interfaceClass,
InvocationHandler invocationHandler) {
return Proxy.newProxyInstance(interfaceClass.getClassLoader(),
new Class[] { interfaceClass }, invocationHandler);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
...... method implementation for invoking main method.
}
}
Step 3: Define our abstract InterceptableDelegate which will call our interceptor methods.
public abstract class InterceptableDelegate extends Delegate {
private final List<Interceptor> interceptors = new LinkedList<Interceptor>(); // TO be populated by subclasses.
protected final void addInterceptor(final Interceptor name) {
this.interceptors.add(name);
}
protected final void removeInterceptor(final Interceptor name)
{
this.interceptors.remove(name);
}
@Override
public Object invoke(Object obj, Method method, Object[] argv) throws Throwable
{
for (final Interceptor i: this.interceptors)
{
i.doBeforeCall(method, argv);
}
Object o = super.invoke(obj, method, argv); // Calls our delegate invoke method.
for (final Interceptor i: this.interceptors)
{
i.doAfterCall(method, argv, o);
}
}
As we have seen our intercepters nicely will be called before and after the target call.and we can implement this kind of mechanism for logging,auditing etc.....
STEP 4: Create subclass SubClassDelegate extending InterceptableDelegate for providing interceptors to be invoked.
public class SubClassDelegate extends InterceptableDelegate {
SubClassDelegate() {
this.addInterceptor(<<Probably audit class interceptor>>);
.......
}
}
our AuditClassIntercepter class skeleton may look like this...
class AuditClassIntercerpter implements Intercerpter {
.... Provide implementations for doBeforeCall() and doAfterCall() methods.
}
STEP 5: Finally create the target class in which when each method is invoked should invoke our interceptor's.
class TargetClass {
public TargetClass newService() {
return (TargetClass)Delegate.newProxyInstance(TargetClass.class,new SubClassDelegate());
}
......
}
Hence from now every method call of targetclass takes place our interceptors will get fired.Ofcourse we can enhance this example in N ways and hope this explanation helps.
Please let me know if any one wants complete code example.Also complete credit to my collegue Humble John for coming up with this intercepter pattern usage idea.
Few References for Intercepter Pattern: http://www.cs.uu.nl/docs/vakken/no/interceptor.pdf
References for Proxy Pattern:
http://en.wikipedia.org/wiki/Proxy_pattern
http://www.javaworld.com/javaworld/jw-02-2002/jw-0222-designpatterns.html
http://userpages.umbc.edu/~tarr/dp/lectures/Proxy-2pp.pdf
Saturday, 1 December 2007
Subscribe to:
Post Comments (Atom)
6 comments:
Hi Prashant,
Excellent post on the Interceptor Pattern. I enjoyed reading it.
Jonathan,
Thanks a lot for encouraging statements.
I enjoy reading your blog
Thanks
Prashant
Really good explanation.
I read interceptor stuff properly with example for first time on net and it worked without any issues in one shot
fazal,
Thanks for your encouraging comments.
Thanks
Prashant
The example with using proxy and interceptoer patterns together is very good.
I get folllowing error when I call print method of TargetClass
TargetClass tgt = new TargetClass();
tgt.newService().print();
java.lang.IllegalArgumentException: com.intercept.TargetClass is not an interface
Can you please let me know what I m missing.
Post a Comment