|
|
06.12.2004 |
|
||||||||||
| Loosely Coupled Components, Part 2 | ||||||||||||
I'm quite interested in the concept of software components and how those ideas can be applied to Java code. Thoughts or ideas I have on this subject get dropped here for the benefit of humanity and my own hubris.
|
In Part 1, I discussed the idea of combining components together in a loose fashion by using Interfaces, but before I start talking about more advanced ideas, I thought I would give an example... a plugin architecture. By way of example, I'm going to describe the inner workings of my Ant task, WebTemplate. When I first designed this beast, I settled on StringTemplate as the template engine, however, that decision would limit the tasks usefulness. Granted, I could have created a number of different tasks for each kind of template engine I might want to use or even a massive if..then statement, but that is pretty inelegant. So I created a simple "plugin" style architecture where I could add template engines to the task without needing access to the source code of the task. In the Ant <webtemplate src="htmldata" dest="html" template="toptemplate" engine="StringTemplate" includes="**/*.htm" ext=".html" /> So, I added a keyword called The plugin isn't the template engine, but would actually be a wrapper around the actual template engine code. This plugin would act kinda like glue code to bind the behavior of my task code with the different APIs of the template engines. Step one then would be to create an interface that each template engine plugin would have to implement. My task could then treat them all similarly: public interface WebTemplatePlugin { public void convert(File srcParent, File destFile, String template, Properties attributes) throws BuildException; } Each plugin would have its In my // We need to get a plugin that matches the engine // the user specified. The plugin must implement // the WebTemplatePlugin interface. // WebTemplatePlugin plugin; try { if (engine.indexOf('.') == -1) engine = "org.howardism.ant." + engine; engine = engine + "Plugin"; // // Get the plugin class and instantiate it... plugin = (WebTemplatePlugin) Class.forName(engine).newInstance(); } catch (Exception e) { throw new BuildException("Can't instantiate " + "plugin: engine="+engine, e); } In order to find the class, I need the "full" classname, that is, a class name with a package. Since I really wanted to just say things like "FreeMarker" or "StringTemplate", I made the assumption that if no package is specified, I can just prepend my own. But the real beauty is the next line. First we get a reference to the class by calling Remember how I said every plugin would have to implement the The other nice feature is that when you use my task, you only need access to the template engine library that you actually use. If you want to use FreeMarker, you just need Thought originally posted on Saturday, 12 June 2004
© 2004-2005, Howard Abrams • Except where otherwise noted, all original content is licensed under a Creative Commons License (see details). |
|||||||||||
|
||||||||||||