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

Sun*_*pta 9 java singleton design-patterns

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

我怎样才能做到这一点?

Pet*_*rey 21

使用一个实例创建枚举

enum Singleton {
    INSTANCE;

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

// You can use
Value v = Singleton.INSTANCE.method(arg);
Run Code Online (Sandbox Code Playgroud)

编辑:Java Enum教程向您展示如何向枚举添加字段和方法.


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

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

// You can use
Value v = Utility.method(arg);
Run Code Online (Sandbox Code Playgroud)

单身人士在实施界面时很有用.这对于使用依赖注入时的测试特别有用.(在单元测试中使用Singleton或实用程序类替换的弱点之一)

例如

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; }
}
Run Code Online (Sandbox Code Playgroud)

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

简而言之,如果您不需要单例来实现接口,那么您可能需要的只是一个实用程序类.


and*_*rey 8

public class Singleton {
    public static final Singleton instance = new Singleton();
    private Singleton() {}
    public void foo() {}
}
Run Code Online (Sandbox Code Playgroud)

然后用

Singleton.instance.foo();
Run Code Online (Sandbox Code Playgroud)

  • 为了完整起见:请添加一个私有的无参数构造函数。 (2认同)