【问题标题】:Singleton Enum implementation with parameters带参数的单例枚举实现
【发布时间】:2013-01-29 06:15:04
【问题描述】:

我正在尝试使用 Java 枚举实现单例。

但是我也想在第一次初始化的时候给构造函数传递一些参数。

我如何做到这一点?使用带参数的单例是一种好习惯吗?

public enum DaoManager {
    INSTANCE;
    private static ILog logger; //for passing the logger;
    private static DatabasePool pool; //passing the Database pool

    public void init(ILog logger, DatabasePool pool){
          this.logger = logger;
          this.pool = pool;   
    }

 }

现在我正在使用 init 方法将记录器和数据库池传递给 DaoManager。

但如果客户端调用 init() 方法失败,那么很有可能失败。

有人可以指导我如何做到这一点吗?

【问题讨论】:

  • 您现在可以设置static 字段而无需类实例吗?
  • 你不能用enum做你想做的事,这种静态是一个糟糕的计划。

标签: java design-patterns


【解决方案1】:

考虑:

public enum DaoManager {
    INSTANCE(FooManager.getLogger(), BarManager.getDataBasePool());
    private static ILog logger; //for passing the logger;
    private static DatabasePool pool; //passing the Database pool

    private DaoManager (ILog logger, DatabasePool pool){
          this.logger = logger;
          this.pool = pool;   
    }

 }

枚举的伟大之处在于它们与类相似。

【讨论】:

  • 如果FooManagerBarManager 属于不提供像getLogger 这样的静态方法的库或操作系统怎么办?
【解决方案2】:

我可以将 init 方法设为私有吗?

如果对象处于有效状态需要某种初始化逻辑。然后应该有一个工厂在向它请求对象时执行此操作。

拥有static init 是糟糕的设计。

顺便说一句,使用 Singleton 更像是一种反模式的测试。拥有全局状态会使对象难以测试。

您不应该限制构造函数,而应使对象 singleton 带有一个小的 's'。使用某种上下文对象来访问应用程序范围内的 DaoManager 单个实例。

applicationContext.getDaoManager()

【讨论】:

  • 对象处于有效状态不需要初始化,但我们需要将记录器和数据库池传递给其他对象。所以我们一直把它放在那里。你觉得我们有什么办法可以满足这个要求吗?
  • 如果您将对象更改为单例并且不使用枚举。然后你可以在构造函数中传递它。就如此容易。我认为这会更有意义。如果有其他要求,请告诉。
  • 应用程序范围的上下文是您保留所有应用程序范围的单例的好地方。这应该是要走的路。欢迎。
【解决方案3】:
public static enum DaoManager {
    INSTANCE;
    private static ILog logger; //for passing the logger;
    private static DatabasePool pool; //passing the Database pool

    public void init(ILog logger, DatabasePool pool){
          this.logger = logger;
          this.pool = pool;   
    }

 }

【讨论】:

  • 客户端如何初始化单例?
  • DaoManager.INSTANCE.init();
  • 如果您将其设为私有,则无法调用它。
  • 另外,你可以随时改变单例的状态,这可能是不可取的。
最近更新 更多