如何使用枚举创建单例类

时间:2015-06-19 14:34:31

标签: java enums singleton

我正在尝试用Java创建一个单例类。 Java5及以上版本的最佳可用解决方案似乎正在使用enum。但我不知道如何使用enum将我的类转换为单例类。以下是我的简化课程:

public class Employee { 
   private int id; 
   private String name; 
   public Employee() {} 
   public int getId() {
      return id; 
   }
   public void setId( int id ) { 
      this.id = id; 
   } 
   public String getName() { 
      return name; 
   } 
   public void setName( String name ) {
      this.name = name; 
   }
}

当我在网上搜索答案时,我发现了以下代码:

public enum EasySingleton{
   INSTANCE;
}

但是我的类变量和方法在哪里?我不知道如何实现这一点。我知道我们可以为enum提供方法,但我的变量在哪里?对此的任何帮助都将非常感激。

P.S。:如果单身人士是邪恶的或反模式,请不要辩论。我很好奇如何使用enum创建单身人士。

3 个答案:

答案 0 :(得分:12)

类和枚举之间的差异并不大。我将第一行代码更改为public enum而不是public class,并添加了实例的名称。

public enum Employee { // changed "class" to "enum"

   INSTANCE; // added name of the (single) instance

   private int id; 
   private String name; 
   Employee() {} // removed "public"
   public int getId() {
      return id; 
   }
   public void setId( int id ) { 
      this.id = id; 
   } 
   public String getName() { 
      return name; 
   } 
   public void setName( String name ) {
      this.name = name; 
   }
}

请记住,如果你想在一个vm中多次运行你的代码,singeltons,枚举实例,静态事物可能会在以后阻碍你。考虑在主类中创建Employee的实例并将其传递给您的应用程序。

除此之外,枚举还有一些其他特殊功能:

  • 您不能extend另一个班级(仅限implements
  • 某些预定义方法(例如static values()getName())可用
  • 构造函数只能是包私有或私有

答案 1 :(得分:3)

你的“员工”课程并不是真正应该是单身人士的课程,但现在就是这样。

public enum Employee { 
   INSTANCE;

   private int id; 
   private String name; 

   private Employee() {}  //enum constructor must be private

   public int getId() {
      return id; 
   }

   public void setId( int id ) { 
      this.id = id; 
   } 

   public String getName() { 
      return name; 
   } 

   public void setName( String name ) {
      this.name = name; 
   }
}

然后你可以做

Employee.INSTANCE.setName("Hello World!");

答案 2 :(得分:0)

(单例模式是否适合您的示例使用在其他答案和评论中讨论。我会假装回答具体问题,即使它可能实际上并不相关。)

Bloch的Effective Java对此进行了很好的讨论。见第17-18页。我直接从这个参考文献中挣扎了!

基本上,您可以使用枚举或私有构造函数强制执行单例模式。 Bloch更喜欢前者,尽管它不太常见。

e.g:

// Enum singleton
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

与公共字段方法等效的功能,并且可以在没有任何样板的情况下进行序列化。即使面对棘手的反射或序列化访问,也只会有一个实例。