Monday, July 09, 2007

Extension Object Pattern : an Eclipse Example

In short an Extension Object pattern is a nice way of extending an interface of class by 3 rd party classes without polluting the base interface of the class.

I am going to take eclipse as an example to explaing this pattern . For those of you , who have done eclipse plugin development . You would have come across ed the interface IAdaptable. This interface is at heart of the Extension Object Pattern implemented by Eclipse .

So what is the Extension Object Pattern ???

Say you have an interface IFile . This interface represents an abstraction of a file . Apart from being a basic file this IFile interface could offer many services . So the question is how do you offer those services .

One simple way would be to extend the IFile interface . Add the extra functionality to the new new interface and have come class implement that new interface . e.g you could have a IUIFile interface . Once you have that interface , you could implement that interface .

But the problem with that approach is that , you end up polluting the base beautiful interface and have a bloated class ( implementor) . Well the above mentioned approach would work if you are fine with extending the object every time you want to implement a new service , but as the number of services increase the class becomes super duper bloated monster .

So how does the extension object pattern help us in solving this evolution problem ??

I ll continue with the IFile interface from eclipse to explain how can we go about using the interface to implement the extension pattern .

We know that IFile might have to support a number of services at some point of time in future . So rather than have IFile implement all the new interfaces , we just implement the IAdaptable interface . This interface is a place holder , saying that the class implementing IFile is now ready to be extended by 3 rd party classes without polluting the base interface IFile.

This Adaptable interface can contain a simple method that does the job of resolving the service to the correct service provider .

public interface IFile extends IAdaptable , .... {
.....

public Object getAdapter(Class adapter);
...
}

}

Now lets say that we want to check if IFile supports ServiceA , or ServiceB.
We can do that now passing ServiceA.class to the getAdpater method .
This method would return a valid object if the service is supported or on the other hand it would return a null object .

Instead of having a number of if conditions in the getAdapter method what eclipse does is that for each interface supported by the type , eclipse creates an adapter factory . The different factories are then registered with an AdapterManager . The getAdapter method then returns
the appropriate AdapterFactory via the AdpaterManager. e.g

public Object getAdapter(Class adapter);
return Platform.getAdapterManager.getAdpater(this,adapter);
}


Something like this can later be used to return the right adapter for intended service.

public interface IAdapterfactory {
public Object getAdapter(Object adaptableObject, Class adapterType);
....
}


The adapter manager uses different adapter factories to resolve the reference for the asked interface , for the given type .

So in this manner multiple behaviors can be added to a single type . This is a nice way to support class extensions.