Reputation: 4636
I have a factory class that serves out a bunch of properties.
Now, the properties might come either from a database or from a properties file.
This is what I've come up with.
public class Factory {
private static final INSTANCE = new Factory(source);
private Factory(DbSource source) {
// read from db, save properties
}
private Factory(FileSource source) {
// read from file, save properties
}
// getInstance() and getProperties() here
}
What's a clean way of switching between these behaviors based on the environment. I want to avoid having to recompile the class each time.
Upvotes: 2
Views: 640
Reputation: 147154
Simply, don't use singletons.
"Parameterise from Above." Construct the required implementation at a place in the code where it makes sense. Pass the instance down to those objects that need it as they are constructed.
Upvotes: 1
Reputation: 597076
You could define something like:
public abstract Factory {
// define all factory methods here
public static Factory getFactory(FactoryType type, Object source) {
if (type == FactoryType.DB) {
return new DbFactory(source);
}
if (type == FactoryType.PROPERTIES) {
return new PropertiesFactory(source);
}
}
}
public DbFactory implements AbstractFactory { .. }
public PropertiesFactory implements AbstractFactory { .. }
instanceof
instead of the enum
new
) with a static methodUpvotes: 0
Reputation: 26132
Dependency Injection is the way to do it.
Generally, using dependency injection in your situation would look like this (example is for Spring DI, would look little different for Guice but the idea is the same):
public interface Factory {
Properties getProperties();
}
public class DBFactory implements Factory {
Properties getProperties() {
//DB implementation
}
}
public class FileFactory implements Factory {
Properties getProperties() {
//File implementation
}
}
public SomeClassUsingFactory {
private Factory propertyFactory;
public void setPropertyFactory(Factory propertyFactory) {
this.propertyFactory = propertyFactory;
}
public void someMainMethod() {
propertyFactory.getProperties();
}
}
//Spring context config
<!-- create a bean of DBFactory (in spring 'memory') -->
<bean id="dbPropertyFactory"
class="my.package.DBFactory">
<constructor-arg>
<list>
<value>Some constructor argument if needed</value>
</list>
</constructor-arg>
</bean>
<!-- create a bean of FileFactory (in spring 'memory') -->
<bean id="filePropertyFactory"
class="my.package.FileFactory">
<constructor-arg>
<list>
<value>Some constructor argument if needed</value>
</list>
</constructor-arg>
</bean>
<!-- create a bean of SomeClassUsingFactory -->
<bean id="MainClass"
class="my.package.SomeClassUsingFactory">
<!-- specify which bean to give to this class -->
<property name="propertyFactory" ref="dbPropertyFactory" />
</bean>
Then, in different environment you just swap your xml config file with some other file that sets the property to filePropertyFactory and you get it passed into the SomeClassUsingFactory.
Upvotes: 6