views:

245

answers:

2

I have a Swing application that I would like to convert from spaghetti to using dependency injection with Guice. Using Guice to provide services like configuration and task queues is going great but I'm now starting on the GUI of the app and am unsure of how to proceed.

The application is basically a JFrame with a bunch of tabs in a JTabbedPane. Each of the tabs is a separate JPanel subclass that lays out the various components and needs services to perform actions when certain buttons are pressed.

In the current application, this looks somewhat like this:

@Inject
public MainFrame(SomeService service, Executor ex, Configuration config) {
    tabsPane = new JTabbedPane();

    // Create the panels for each tab and add them to the tabbedpane
    somePanel = new SomeTabPanel(service, ex, config);
    tabsPane.addTab("Panel 1", somePanel);

    someOtherPanel = new SomeOtherTabPanel(service, ex, config);
    tabsPane.addTab("Panel 2", someOtherPanel);

    ... do more stuff
}

Obviously, this doesn't exactly follow DI best practices. I don't want to have to @Inject the tabs because that would get me a constructor with dozens of parameters. I do want to use Guice to inject the required dependencies into whatever tab objects I need without me having to pass all of those dependencies to the tab constructors.

All of the dependencies for the tab objects are services that my Module knows about, so basically all I think I want to do is to ask Guice for the required objects and have them constructed for me.

A: 

Couldn't you just inject the service in the JFrame and let the tabs ask for the service / configuration, like so

this.getTopLevelAncestor().getService()

Of course this only works if called after they have been added to a container.

Helper Method
I think that would make the spaghetti even worse. It would add lots of casts to `MainFrame` and actually reduce the potential to re-use any of these classes because they would be tightly coupled to `MainFrame` instead of only their dependencies like they are now.
Gerco Dries
+3  A: 

Could you use Multibinding to bind all of your tabs as a Set? If they implemented some interface that allowed you to get the name to use for the tab, you could then just loop through adding the tabs from the set. You'd probably need to figure something out as far as ordering the tabs though.

ColinD
A possibility I will consider. I believed Multibinding to be only for cases where you don't know the amount of objects you are going to get, or their actual types. In this case I know exactly how many and which types, I just don't want to construct them manually so I didn't think Multibinding was a good enough match for what I wanted to do.
Gerco Dries
I'd agree with @ColinD. +1 for multibindings
gpampara