Refactoring from Singleton Anti-Pattern to Dep Injection
Hi,
I'm currently refactoring a large Swing application to use the Spring Framework. Unfortunately, the application currently makes heavy use of the Singleton "anti-pattern" to access the business service layer.
So far, it has been easy to make the IOC container instantiate the service layer objects as beans and to inject them into objects at the "top layer" of the application, that is objects directly involved with the main frame. However, what about objects farther down the food chain? For example (somewhat contrived), what about a model object for a panel that is part of another panel on a dialog that is accessed from a child frame of the main frame? The dependency chain could look like this, for example:
Code:
MainFrame
->ChildFrame
->DialogLaunchedFromChildFrame
->BigPanelOnDialog
->LittlePanelInsideBigPanel
->LittlePanelModel
->MyServiceLayerObject
Currently LittlePanelModel accesses MyServiceLayerObject in singleton fashion. For example:
Code:
MyServiceLayerObject.getInstance.doSomeService()
The question is, how should I refactor this code so that LittlePanelModel does not have to access MyServiceLayerObject in singleton fashion. The way I see it, there are several refactoring options here:
1) Instantiate ALL of the objects in the IOC container and use dependency injection to inject the service layer dependency into LittlePanelModel. This may seem like the logical choice except when you look at the big picture. This sort of long dependency chain is seen all over the application because there are many, many screens, dialogs and panels in the app. I would have to configure several hundred objects in the application context configuration files. Some of you say "what's wrong with that"? In the long run, I think it might be workable but in the short run, I can only refactor this app in stages. I can't make all of the beans IOC-managed all at once; I have to move towards this goal slowly.
2) Get the container to Inject the dependency into MainFrame and then pass the dependency along as each object instantiates its helper object in the next link of the dependency chain. I don't particularly like this because objects in the middle of the chain are not directly dependent on the service layer objects; to keep coupling low, I don't want to introduce unnecessary dependencies.
3) Use "one singleton to rule them all" (this hiliarious Lord of the Rings-ish quote is from the javadocs for Spring's BeanFactoryBootstrap class). In other words, allow singleton access to the bean factory or application context that holds all of the service layer objects. This is still a singleton but at least there's only ONE singleton in the entire app instead of one for each service object.
Comments or advice?
Cheers,
Joe
"All your bean are belong to us" - Spring Framework's IOC Container