如何设计可以选择作为Singleton运行的Java类? [英] How to design Java class(es) that can optionally function as Singleton?

查看:95
本文介绍了如何设计可以选择作为Singleton运行的Java类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是该场景:

public class A {    
    public A {}
    void doSomething() {
        // do something here...
    }
}

现在,该类已设置,您可以在其中创建多个实例。但是我也看到了一个需要,我可能想要将类限制为只有一个实例,即Singleton类。

Right now, the class is setup where you can create multiple instances. But I also see a need where I might want to restrict the class to only one instance, i.e. Singleton class.

问题是我不知道该如何去做完成两个目标的设计:多个实例和一个实例。在一堂课中听起来不太可能。我想我需要使用派生类,抽象类,接口,其他东西或某种组合。

The problem is I'm not sure how to go about the design of accomplishing both goals: Multiple instances and one instance. It doesn't sound possible to do in just one class. I imagine I'll need to use a derived class, an abstract class, interface, something else, or some combination.

我应该创建A类作为基类,创建一个作为单例类的派生类?

Should I create class A as a base class and create a derived class which functions as the singleton class?

推荐答案

当然,首先应该总是质疑必要性使用单身人士。但有时,它们只是解决某些问题的务实方式。

Of course, the first thing should always be to question the necessity to use singletons. But sometimes, they are simply a pragmatic way to solve certain problems.

如果是这样,首先要理解的是:没有解决方案可以强制执行您的要求并防止误用,但这里有一个模式,通过将意图转换为有意义的代码来帮助很多:

If so, the first thing to understand is: there is no solution that can "enforce" your requirements and prevent mis-use, but here is a "pattern" that helps a lot by turning "intentions" into "meaningful" code:

首先,我有一个表示功能的界面:

First, I have an interface that denotes the functionality:

interface WhateverService { void foo() }

然后,我有一些想法:

class WhateverServiceImpl implements WhateverService {
  @Override
  void foo() { .... }

现在,如果我需要那个以单身形式存在的东西,我做

Now, if I need that thing to exist as singleton, I do

enum WhateverServiceProvider implements WhateverService {
  INSTANCE;
  private final WhateverService impl = new WhateverServiceImpl();
  @Override
  void foo() { impl.foo() }

最后,一些客户端代码可以这样做:

and finally, some client code can do:

WhateverService service = WhateverServiceProvider.INSTANCE;
service.foo()

(但当然,您可能不想直接分配一个服务对象,但你可以在这里使用依赖注入)

(but of course, you might not want to directly assign a service object, but you could use dependency injection here)

这样的架构给你:


  1. 核心功能实现单例概念之间的明确分离

  2. 保证单身语义(如果有一件事,那就是Java枚举真的很有用......那就是:提供万无一失的单身人士!)

  3. Full 可测试性(你看 - 当你刚才使用枚举时,没有将其作为接口使用...那么你很难在客户端代码中模拟该对象 - 因为你不能直接模拟枚举。)

  1. A clear separation between the core functionality, its implementation and the singleton concept
  2. Guaranteed singleton semantics (if there is one thing that Java enums are really good for ... then it is that: providing fool-proof singletons!)
  3. Full "testability" (you see - when you just use the enum, without making it available as interface ... then you have a hard time mocking that object in client code - as you can't mock enums directly).

更新 - 关于线程安全:

Update - regarding thread safety:

我不确定你究竟是什么意思单身概念。

I am not sure what exactly you mean with "singleton concept".

但是我们可以这样说:当你使用这样的枚举时,保证有一个完全实例化一个INSTANCE对象,Java语言保证。但是:如果有几个线程转向枚举,并且并行调用foo()......你仍然在处理围绕这些场景的所有潜在问题。所以,是的,枚举创造是线程安全的;但是你的代码正在做什么......取决于你。那么锁定或其他任何有意义的东西。

But lets say this: it is guaranteed that there is exactly one INSTANCE object instantiated when you use enums like that, the Java language guarantees that. But: if several threads are turning to the enum, and calling foo() in parallel ... you are still dealing with all the potential problems around such scenarios. So, yes, enum "creation" is thread-safe; but what your code is doing ... is up to you. So is then locking or whatever else makes sense.

这篇关于如何设计可以选择作为Singleton运行的Java类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆