views:

237

answers:

7

Hi Guys,

I was wondering how to package the factories I have in my application. Should the Factory be in the same pacakage as the classes that use it, in the same package as the objects it creates or in its own package?

Thanks for yout time and feedback

+10  A: 

Usually factories are in the same package as the objects they create; after all their purpose is to create those objects. Usually they are not in a separate package (there is no reason for that). Also having the factory be in the same package as the objects they create allows you to exploit package visibility.

Francis Upton
To elaborate, by *exploit package visibility*, I think you mean that the concrete types of the instances created by the factory can be package-scoped -- not publicly visible -- and the factory is then the only public means to create types conforming to some interface. Even tighter lockdown comes by defining the types created by the factory as abstract classes with *package-private* constructors; subclasses may then be defined only within the containing package. http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html
seh
A: 

I like to put the factory in the package it is creating objects for, naming is key here, if naming is clear and transparent it will help maintenance effort down the line.

For example an action factory could be structured as:

  • package org.program.actions
  • interface org.program.actions.Action
  • enum org.program.actions.ActionTypes
  • factory org.program.actions.ActionFactory (or .ActionManager)
  • action implementation classes org.program.actions.LogAction, etc.

Following patterns like this throughout projects help project members to find classes where they actually are located in projects they haven't been involved in before.

rsp
A: 

That wholly depends on the way you're intending to use said factories. Sometimes it makes sense to put a factory in its own package.

You might for example have an interface, foo.bar.ui.Interface. You want to have different implementations of that interface, one for AWT, one for Swing, one for the console, etc. Then it would be more appropriate to create a foo.bar.ui.swing.SwingInterfaceFactory that creates a foo.bar.ui.swing.SwingInterface. The factory for the foo.bar.ui.awt.AWTInterface would then reside in foo.bar.ui.awt.AWTInterfaceFactory.

Point is, there is no always-follow-this rule. Use whatever is appropriate for your problem.

Bombe
Can't agree here. I don't see how cross-package dependencies are ever a good idea. Also do not see the use in creating a package that would have one class. Another thing - wouldn't the point of such a factory be to hide Swing and AWT from the caller? I would think you'd have a single factory and concrete AWT and Swing implementations of foo.bar.ui.Interface.Also, "Release/Reuse" is in fact a generally accepted "always-follow-this" principle. I'm sure someone can think of an exception (I can't off-hand), but as far as general principles go, this one is pretty solid.
Dave Sims
A: 

Bombe, in your example you are still putting the Factory in the same package as the objects they create :-) Which is the right way to do it and what everyone else has been saying!

Johnny Keys
+2  A: 

The unit of reuse is the unit of release. This means there shouldn't be coupling across packages, as the package is generally the lowest granularity of release. When you organize a package, imagine yourself saying, "here's everything you need to use these classes."

Dave Sims
A: 

why not. make it as close as possible if there is no other objections. actually why not

public interface Toy
{
    static class Factory
    {
        public static final Toy make() { ... }
    }
}

Toy toy = Toy.Factory.make();

HA!

but make() shouldn't statically depend on subclasses of Toy, that would be bad. it can do some dynamic magic, depends on your factory strategy.

irreputable
+3  A: 

The whole point of a Factory is to have a configurable way to create implementation instances for interfaces. The convention to have the factory in the same package as the implementation classes it provides adds a completely unnecessary restriction you're unlikely to meet in the future. Also if the implementation returned is not the same across all contexts, it makes even less sense to have it in the same package.

For example, imagine a service lookup factory that is shared between the client and server part of an application, which returns a client side implementation (which resides in a client-only package) on the client, and a server side implementation (in a server-only package) when called from within the server's runtime.

Your factory may even be configurable (we do this by having a XML file which defines which implementation class to return for which interface), so the implementation classes can easily be switched, or different mappings can be used for different contexts. For example, when unit testing we use a configuration which returns mockup implementations for the interfaces (do be able to do unit tests that are not integration tests), and it would make no sense at all to require those mockup implementations to be in the same package as the factory, as they're part of the testing code rather than the runtime code.

My recommendation:

  • Don't add any package restrictions on the implmentation classes, as you don't know which implementations are used in the future, or in different contexts.
  • The interfaces may be in the same package, but this restriction is also unnecessary and only makes the configuration rigid.
  • Configurable factories (such as a service lookup) can be reused and shared across projects when the interface/implementation mapping isn't hardcoded. This point alone justifies having the factory separated from both the interfaces and the implementation classes.
Peter Walser
I agree with your points here, but that does not mean that you must package the factory some place other than the implementation classes. There may be cases where all of the implementation classes are in the same package and will always be. I think both situations are reasonable. Depends on the app.
Francis Upton
Yes, very often the implementation classes will remain the same for the whole life cycle of a project, and usually there will be one implementation class per interface in the Factory.But nevertheless the point of a Factory is to keep it open and allow implementation classes to be exchanged in the future. Adding package restrictions to the factory would violate its intention and hinder refactoring (by exchanging the implementation) in the future.Even for projects where you're pretty sure that the implementation classes are never exchanged, it's better to keep this point open.
Peter Walser