首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >编程到接口的Java单例enum?

编程到接口的Java单例enum?
EN

Stack Overflow用户
提问于 2016-03-17 10:53:35
回答 4查看 364关注 0票数 3

这是我在这里的第一篇文章,所以我会尽量精确。这是一个大学项目,我们必须创建一个鱼缸模拟之上的OO架构,我们单独制作。我正在探索单例的用途,并发现它们非常有用,但是在线阅读我目前实现它的方式并不是线程安全的。

我目前实现它的方式(认为这是懒惰的方法)--注意:我们必须通过接口

代码语言:javascript
运行
复制
public interface myInterface
{
  void foo();
}

public class myClass implements myInterface
{
  private static myInterface instance;

  private myClass(){}

  private static myInterface Instance()
  {
     if(instance == null)
       instance = new myClass();

     return instance;
  }

  public void foo()
  {
    //Do stuff
  }

  public void bar()
  {
   //Do More Stuff
  }
}

这是很好的工作,但它不是线程安全,我可以添加同步关键字到getter,但我已经读过,这是相当沉重的系统,我有相当多的单颗。

代码语言:javascript
运行
复制
private synchronized static myInterface Instance()
{
  if(instance == null)
    instance = new myClass();

  return instance;
} 

然后,我转到了一个,它是线程安全的,对系统不太重要,但是我不确定如何将它编程到接口上。

代码语言:javascript
运行
复制
public enum myClass implements myInterface
{
  INSTANCE;
  private myClass(){}

  public void foo()
  {
    //Do stuff
  }

  public void bar()
  {
   //Do More Stuff
  }
}

在接口编程中,我的意思是,当我调用单例时,我只能访问接口中的方法(如果我错误地引用了这个方法,请纠正我)。这就是我做单例枚举失败的地方。例如:对于懒惰的单例,我不能在接口中调用它,因为它不在接口中:

代码语言:javascript
运行
复制
 myClass.Instance().bar();

但它可以称之为这是正确的,因为它是在接口中。

代码语言:javascript
运行
复制
myClass.Instance().foo();

但是,使用enum,我可以将它称为非编程到接口。

代码语言:javascript
运行
复制
myClass.INSTANCE.bar();

我理解它为什么要这样做,因为类是enum,所以它可以调用枚举类中的所有内容。因此,在我为这篇长篇文章致歉之后,主要的问题是:我能否使枚举版本仅在接口中声明的调用方法?

如果它不能在系统上有多重的同步方法,我会有大约4-6个?

请注意:尽管这是一个大学项目,我们只是在一个线程上运行模拟,所以它甚至不需要线程安全。我不太理解多线程,但我认为这是一个很好的学习机会。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-03-17 11:10:07

如果您喜欢枚举路由,也可以隐藏您的枚举实现:

代码语言:javascript
运行
复制
public interface Singleton {
    void foo();
}

public final class SingletonAccessor {

    public static Singleton getInstance() {
        return SingletonImpl.INSTANCE;
    }

    private SingletonAccessor() {
    }

    private enum SingletonImpl implements Singleton {
        INSTANCE;
        public void foo() {
            // ...
        }
        public void bar() {
            // ...
        }
    }

}

编辑

正如Peter在评论中指出的那样,您甚至可以为SingletonAccessor使用枚举:)

代码语言:javascript
运行
复制
public enum SingletonAccessor {

    SINGLETON;

    public Singleton get() {
        return SingletonImpl.INSTANCE;
    }

    private enum SingletonImpl implements Singleton {
        INSTANCE;
        public void foo() {
            // ...
        }
        public void bar() {
            // ...
        }
    }

}
票数 2
EN

Stack Overflow用户

发布于 2016-03-17 11:05:52

您可以将其转换到接口或

代码语言:javascript
运行
复制
myInterface my = myClass.INSTANCE;
my.foo();

您仍然可以使用这样的方法

代码语言:javascript
运行
复制
myClass.getInstance().foo();

但这并不是IMHO的真正解决方案。

我可以使枚举版本仅在接口中声明的调用方法吗?

最终,您必须决定在实例(即public )上需要哪些方法。如果将方法或字段设置为公共的,则可以访问它,如果不希望能够访问它,则将其设置为私有。

在某种程度上,你必须相信你知道自己在做什么,你做事情是有原因的。你不需要想办法来阻止你自己编写的调用代码。

票数 1
EN

Stack Overflow用户

发布于 2016-03-17 11:08:32

只需这样更改您的单例类即可:

代码语言:javascript
运行
复制
public class myClass implements myInterface
{
  private static myInterface instance = new myClass();

  private myClass(){}

  private static myInterface Instance()
  {
     return instance;
  }

  public void foo()
  {
    //Do stuff
  }

  public void bar()
  {
   //Do More Stuff
  }
}

这将确保在类加载时创建单例对象,并且不需要担心Instance()方法中的争用条件。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36058443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档