|Oxyware||Oxyware.com > Patterns > Exported Interface|
To allow an independently deployable component written in a statically-typed language (such as C++ or Java) to reverse an outgoing dependency so that the component can be compiled.
Say we wish to write a GUI builder that simplifies the task of laying out a complex user interface, and we wish to sell this as a commercial tool to developers. Naturally, we want to be able to generate as much of the GUI code as possible to add value to our product. Therefore we want to be able to generate code to handle button clicks such as this:
But how do we know what function to call? We can't know any of the names of the developer's functions as our product is a general product that can be bought off the shelf (we hope!). So how can we compile our code? Do we just leave the button handler as a stub function with a "fill in this bit yourself later" comment and no indication of how to fill it in, or do we try to write some code? If we write some code, how can we compile it if we're calling something whose name we don't (and cannot) know?
What we can do is to export an abstract interface from our component and get the developer to implement that interface and write the button handler like this:
Use the Exported Interface pattern whenever a component needs to call code outside of itself that cannot be known at compile time.
The Exported Interface pattern has the following consequences:
The important part of this pattern is that the interface must be in the same component as the core class.
In C++, which has weak package management, this might be implemented using namespaces and delivering a source header file for the interface to the user along with the binary code for the component.
In Java the package construct would be used; the exported interface would be declared public and the internals of the component would be accessible only within the package itself.
Returning to the GUI builder example, we might have GUI builder code like this:
the exported interface would be:
and the concrete implementation class might be:
COM uses this principle for all "outbound" interfaces. Java uses it as part of the JavaBeans framework when defining event listeners. Java servlets are another example.
This pattern is strongly related to a group of patterns called Abstract Server, Abstract Client and Abstract Partner, the purpose of which is to decouple the caller and the callee. In the case of these abstract pattern the interface is often optional, whereas for this pattern the exported interface is essential as the class that is to implement that interface cannot be known in a composable component-based system.
The external implementing class (or classes) may well be external Strategy objects as a way of customising the components using external code.