akula1001
akula1001

Reputation: 4636

dynamic behavior of factory class

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

Answers (3)

Tom Hawtin - tackline
Tom Hawtin - tackline

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

Bozho
Bozho

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 { .. }
  • You can use instanceof instead of the enum
  • if you want your factories to be singleton, replace instantiation (new) with a static method

Upvotes: 0

bezmax
bezmax

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

Related Questions