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

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

问题描述

场景如下:

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

现在,该类已设置好,您可以在其中创建多个实例.但我也看到需要将类限制为只有一个实例,即单例类.

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() }

然后,我对此有一些暗示:

Then, I have some impl for that:

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

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

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

此类架构为您提供:

  1. 明确区分核心功能实现单例概念
  2. 保证单例语义(如果有一件事 Java 枚举真的很适合……那么就是:提供万无一失的单例!)
  3. 完整的可测试性"(您会看到 - 当您只使用枚举而不将其用作接口时……那么您很难在客户端代码中模拟该对象 - 因为您不能直接模拟枚举).

更新 - 关于线程安全:

Update - regarding thread safety:

我不确定您对单例概念"的确切含义.

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

但是可以这样说:当您使用这样的枚举时,可以保证恰好一个实例化对象,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.

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

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