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

时间:2011-12-22 10:41:47

标签: java design-patterns singleton

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

我该怎么做?

7 个答案:

答案 0 :(得分:21)

创建一个包含一个实例的枚举

enum Singleton {
    INSTANCE;

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

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

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


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);

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

e.g。

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(),您可以在外部控制时间,即每次您的时间戳都相同进行测试。

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

答案 1 :(得分:8)

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

然后使用

Singleton.instance.foo();

答案 2 :(得分:2)

另一种方法是singleton holder idiom,它根据需要提供初始化:

public class Something {
        private Something() {
        }

        private static class LazyHolder {
                public static final Something INSTANCE = new Something();
        }

        public Something getInstance() {
                return LazyHolder.INSTANCE;
        }
}

(修改示例,使得getInstance方法不是静态的)

请注意,应该尽可能避免像这样的独立单例,因为它会促进全局状态,导致难以置信的代码,并依赖于单个类加载器上下文来命名一些可能的缺点。

答案 3 :(得分:1)

遵循“Effective Java”第2版中的Joshua Bloch enum食谱。这是创建单身人士的最佳方式。

我不明白为什么会出现这么多。单身人士不是一个名誉扫地的设计模式吗? GoF今天将在岛外投票。

答案 4 :(得分:1)

你可以使用一个IoC容器(例如Google Guice)并将你的类用作单身(渴望或懒惰 - 这取决于你的需要)。它非常简单灵活,因为实例化是由IoC框架控制的 - 例如,如果您决定让您的类不是单例,那么您不需要进行任何代码更改。

答案 5 :(得分:0)

使用对象工厂,从此工厂获取单件对象。

ObjectFactory factory;
....
MySingletonObject obj = factory.getInstance(MySingletonObject.class);

当然,有很多框架可以帮助您实现这一目标。 弹簧框架是一种流行的选择。

答案 6 :(得分:0)

从构造函数中你需要chceck如果已经有某个类的实例。因此,您需要在静态变量或类中存储对单例实例的引用。然后在singleton的构造函数中,我总是会检查是否存在singleton类的现有实例。如果是,我不会做任何事情,如果不是我会创建它并设置参考。