| IocContainerInternals/TheBasics/TheGlorifiedHashMap |
UserPreferences |
| JicarillaWiki | FrontPage | Overview | Articles | GetStarted | Sourceforge Project Page | RecentChanges |
This wiki is in 'slumber' mode, just like its associated sourceforge project. Edits are disabled, the content is potentially stale and is not maintained. That said, it contains some really useful stuff still. Enjoy!
We're going to start with a stupid Swing example that doesn't use a container at all:
public class NoSwingContainerAtAll
{
public final static void main( String[] args )
{
// Setup Stage
JButton[] buttons = new Object[10];
// Assembly Stage
for( int i = 0; i < buttons.length; i++ )
buttons[i] = new JButton( "Button " + i );
JFrame frame = new JFrame( "So...many...roses..." );
JRootPane pane = frame.getRootPane();
for( int i = 0; i < container.length-1; i++ )
pane.add( buttons[i] );
// Initialization Stage
((JFrame)container[container.length-1]).setVisible(true);
}
}
The simplest container is an array. Here's an example:
public class ArrayBasedSwingContainer
{
public final static void main( String[] args )
{
// Setup Stage
Object[] container = new Object[11];
// Assembly Stage
for( int i = 0; i < container.length-1; i++ )
container[i] = new JButton( "Button " + i );
JFrame frame = new JFrame( "Worst episode ever!" );
JRootPane pane = frame.getRootPane();
for( int i = 0; i < container.length-1; i++ )
pane.add( (Component)container[i] );
container[container.length-1] = frame;
// Initialization Stage
((JFrame)container[container.length-1]).setVisible(true);
}
}
in this example, the array that's aptly dubbed "container" is a container for a set of swing components. The added value of using a container instead of just wiring the components together manually is probably negative. I hope you agree the above sample makes even less sense than the first one. Bear with me please. Let's move up to a HashMap...
public class HashMapBasedSwingContainer
{
public final static void main( String[] args )
{
// Setup Stage
Map container = new HashMap();
// Assembly Stage
for( int i = 0; i < 10; i++ )
{
JButton button = new JButton( "Button " + i );
container.put( ""+i, button );
}
JFrame frame = new JFrame( "Worst episode ever!" ); // D
JRootPane pane = frame.getRootPane(); // '
for( int i = 0; i < container.length-1; i++ ) // o
pane.add( container[i] ); // h
container.put( "frame", frame ); // !
// Initialization Stage
container = Collections.unmodifiableMap( container ); // !
((JFrame)container.get("frame")).setVisible(true); // !
}
}
seems like no just about no gain whatsoever. The trick now is that we're going to make our container more intelligent (we'll be making it less general at the same time). I want a container that automatically provides me with a JFrame (you can call the JFrame a "container facility" if you're into fancy terms) automatically, and that understands to add any button I feed it to that frame. The need for such a thing is highly debatable, but so is following a large amount of floating donuts and falling down a steep cliff doing so. While I'm at it, lets make the container worry about what exactly goes on during "initialization" as well. In other words, make the container handle the "D'oh!!!". We now get something like
public class CustomHashMapBasedSwingContainer
{
public final static void main( String[] args )
{
// Setup Stage
CustomHashMap container = new CustomHashMapImpl(
"You don't make friends with salad! " +
"You don't make friends with salad!");
// Assembly Stage
for( int i = 0; i < 10; i++ )
{
JButton button = new JButton( "Button " + i ); // My eyes, my beautiful eyes!
container.put( ""+i, button );
}
// Initialization Stage
container.initialize();
}
}
There's one more thing we should do here to complete the picture: the container needs to be in charge of the "new" keyword. Let us put the "I" in "IoC". It goes a little something like this:
public class IoCButtonContainer
{
public final static void main( String[] args )
{
// Setup Stage
IoCButtonContainer container = new IoCButtonContainerImpl(
"You don't make friends with salad! " +
"You don't make friends with salad!");
// Assembly Stage
for( int i = 0; i < 10; i++ )
container.addJButton( ""+i, "Button " + i ); // It only hurts a little!
// Initialization Stage
container.initialize();
}
}
this example is now 4 lines shorter (50%!) than the original one that didn't use a container at all. It may be a little less apparent immediately exactly what is going on, but that's just because we don't actually know what IoCButtonContainer does or what its contract is. Imagine having a big real life application, like one with, oh, 1500 buttons of 100 different kinds, all with slightly different configuration. Saving 50% of the lines of code in an application like that seems like a smart idea. Furthermore, we've lost that totally ugly 'new' for all those buttons. You might imagine that this allows all sorts of tricks, optimizations, and code security. We'll save the example of that for a later chapter, but hold on to that thought.