在不使用静态方法的情况下创建类单例

2022-09-05 00:37:46

我需要创建一个单例类,而不保留静态方法。

我该怎么做?


答案 1

创建包含一个实例的枚举

enum Singleton {
    INSTANCE;

    private Field field = VALUE;
    public Value method(Arg arg) { /* some code */ }
}

// You can use
Value v = Singleton.INSTANCE.method(arg);

编辑:Java 枚举教程向您展示了如何将字段和方法添加到枚举中。


BTW:通常当你可以使用单例时,你并不需要一个,因为实用程序类会做同样的事情。更短的版本只是

enum Utility {;
    private static Field field = VALUE;
    public static Value method(Arg arg) { /* some code */ }
}

// You can use
Value v = Utility.method(arg);

单例的有用之处在于它们实现接口时。这对于使用依赖关系注入时的测试特别有用。(在单元测试中使用单例或实用程序类替换的弱点之一)

例如:

interface TimeService {
    public long currentTimeMS();
}

// used when running the program in production.
enum VanillaTimeService implements TimeService {
    INSTANCE;
    public long currentTimeMS() { return System.currentTimeMS(); }
}

// used in testing.
class FixedTimeService implements TimeService {
    private long currentTimeMS = 0;
    public void currentTimeMS(long currentTimeMS) { this.currentTimeMS = currentTimeMS; }
    public long currentTimeMS() { return currentTimeMS; }
}

如您所见,如果您的代码在任何地方都使用TimeService,则可以在外部注入或可以控制时间的位置,即每次运行测试时,您的时间戳都是相同的。VanillaTimeService.INSTANCEnew FixedTimeService()

简而言之,如果您不需要单例来实现接口,则可能只需要一个实用程序类。


答案 2
public class Singleton {
    public static final Singleton instance = new Singleton();
    private Singleton() {}
    public void foo() {}
}

然后使用

Singleton.instance.foo();

推荐