【问题标题】:How can I call an instance of a singleton class based on a properties file in java?java - 如何根据java中的属性文件调用单例类的实例?
【发布时间】:2013-04-15 23:32:29
【问题描述】:

我有一个简短的 Java 问题。哦,我对 Java 和 stackoverflow 都很陌生,所以请体谅:)

让我试着更好地解释我的问题。所以我有两个遵循单例模式的类,比如 A 类和 B 类:

public class A
{
    private static final A INSTANCE = new A()

    public static A getInstance()
    {
         return A.INSTANCE;
    }
}

public class B
{
    private static final B INSTANCE = new B()

    public static B getInstance()
    {
         return B.INSTANCE;
    }
}

现在我正在从另一个类访问这些类的实例,比如说 C:

public class testClassC
{
    A class_instance = A.getInstance();
    //or
    //B class_instance = B.getInstance();
}

我想要实现的是(此时的语法可能完全错误,我一直在尝试不同的东西,但没有一个对我有用):

有一个 .properties 文件如下:

 className=A

然后以某种方式从该属性文件中读取类名,这样当我将 A 更改为 B 时,我的 testClassC 将为我获取 B 的实例。

我怎样才能做到这一点?哦,又一次 testClassC 是一个测试类,我有一大堆 JUnit 测试类,那么解决这个问题的最佳方法是什么?

谢谢

【问题讨论】:

  • 您希望它有多灵活?如果您不太关心使其灵活,您可以创建一个 Map 来存储类的名称以及该类的单例。
  • @RobWatts 我会在哪里存储该 Map 对象?基本上我拥有的是 3 种类型的存储类:RAM、XML 和 SQL。然后我有测试类来测试我的存储。我想要做的是有一个属性文件,我可以在其中将我的类名更改为 RAM,我的测试类将创建一个 RAM 存储类的实例,并对其进行测试。
  • 您应该阅读依赖注入,因为这正是您要寻找的。这是一个 article 覆盖 Spring DI。你应该仔细阅读它,尤其是第 6 章。
  • 我认为 Spring 可能是矫枉过正。我会选择guice - 它的重量级要小一些。

标签: java properties junit singleton instance


【解决方案1】:

这是一个使用抽象工厂模式的示例。

您有一个 interface 来定义您的类 - 您需要它以便抽象实际实现。

然后你有一个工厂接口,它定义了newInstance 方法。这使得将单例模式替换为工厂模式变得非常容易。它还可以轻松更改工厂实现以进行测试。

interface MyInterface {
}

interface MyInterfaceFactory {

    MyInterface newInstance();
}

class MyInterfaceFactoryFromProperties implements MyInterfaceFactory {

    final Class<? extends MyInterface> myInterfaceImpl;

    {
        final Properties properties = new Properties();
        try {
            properties.load(MyInterfaceFactoryFromProperties.class.getResourceAsStream("className.properties"));
        } catch (IOException ex) {
            throw new ExceptionInInitializerError(ex);
        }
        final String className = properties.getProperty("class.name");
        try {
            myInterfaceImpl = (Class<? extends MyInterface>) MyInterfaceFactoryFromProperties.class.forName(className);
        } catch (ClassNotFoundException ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    @Override
    public MyInterface newInstance() {
        try {
            return myInterfaceImpl.newInstance();
        } catch (InstantiationException ex) {
            throw new RuntimeException(ex);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(ex);
        }
    }
}

因此您的工厂实现将遵循此模式,但您可以缓存值以使其成为单例。

此方法从类路径加载属性文件 - 显然这可以更改为文件系统位置。

【讨论】:

  • 也感谢所有其他响应者,是的,我将阅读依赖注入。我们在速成课程中简要介绍了它,但从未真正强调过。我想我很快就会知道它的作用。
猜你喜欢
  • 2023-03-08
  • 2015-02-18
  • 2018-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
相关资源
最近更新 更多