Java 工厂类的动态行为

Java 工厂类的动态行为,java,design-patterns,oop,Java,Design Patterns,Oop,我有一个工厂类,它提供一系列属性 现在,属性可能来自数据库或属性文件 这就是我想到的 public class Factory { private static final INSTANCE = new Factory(source); private Factory(DbSource source) { // read from db, save properties } private Factory(FileSource source)

我有一个工厂类,它提供一系列属性

现在,属性可能来自数据库或属性文件

这就是我想到的

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
}
根据环境在这些行为之间切换的干净方式是什么。
我希望避免每次都必须重新编译该类。

您可以定义如下内容:

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
    而不是
    enum
  • 如果希望工厂是单例的,请用静态方法替换实例化(
    new

依赖注入就是一种方法

  • 概述:
  • Spring DI:
  • Guice DI:
通常情况下,在您的情况下使用依赖项注入看起来是这样的(例如Spring DI,对于Guice看起来没有什么不同,但想法是一样的):

公共接口工厂{
属性getProperties();
}
公共类DBFactory实现工厂{
属性getProperties(){
//数据库实现
}
}
公共类FileFactory实现工厂{
属性getProperties(){
//文件实现
}
}
公共类使用工厂{
私人工厂产权工厂;
public void setPropertyFactory(Factory propertyFactory){
this.propertyFactory=propertyFactory;
}
public void somemain方法(){
propertyFactory.getProperties();
}
}
//Spring上下文配置
一些构造函数参数,如果需要的话
一些构造函数参数,如果需要的话

然后,在不同的环境中,您只需将xml配置文件与将属性设置为filePropertyFactory的其他文件交换,然后将其传递到SomeClassUsingFactory。

简单地说,不要使用单例


在代码中有意义的地方构造所需的实现。将实例向下传递给那些在构建时需要它的对象。

我想补充一点,这称为控制反转,依赖注入是IoC的一个子类型。您可以在此处了解更多信息:@Max“IoC”通常用于[true]框架的上下文(其中库是应用程序,向上调用“业务”代码)。我指的是一种简单的、无全局性的代码风格,具有一种严格的实现层次结构(ish)依赖性。游泳。我当然会建议不要使用依赖注入框架(直到它们有意义为止)。是的,它是“典型”在这种情况下使用的。但是手动操作并不能使它成为IoC。@Max我认为IoC意味着回调,这不是这里发生的事情。“paraperise…”——应该参数化吗?或者,引入一个
工厂()
constructor,它检查环境属性并分别调用文件或数据库构造函数。如果在项目的整个生命周期中只有两种方法可以获取属性,那么它将起作用。但是如果需要添加一些TCPPropertyFactory或XmlPropertyFactory?每次出现新的PropertyFactory时,都必须更改该Factory()构造函数。使用适当的IoC机制,您只需编辑配置文件即可。
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>