java Java中的单例和继承

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5427818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:04:32  来源:igfitidea点击:

singleton and inheritance in Java

javadesign-patternsinheritancesingleton

提问by sura

I have a base class that captures some functionality common to two classes. In other words, I can create one base class and make these two classes subclasses of that base class. However, for each of these sub classes, the number of instances can be created is 1 (i.e. each sub class has to be a singleton). I googled and found that there's a reasonable debate going on over this. Although there are several solutions available, I am not sure whether they would fit in my case.

我有一个基类,它捕获了两个类共有的一些功能。换句话说,我可以创建一个基类并使这两个类成为该基类的子类。但是,对于这些子类中的每一个,可以创建的实例数为 1(即每个子类必须是单例)。我用谷歌搜索,发现有一个合理的辩论正在进行中。尽管有多种解决方案可用,但我不确定它们是否适合我的情况。

can anyone tell me how I should design this?

谁能告诉我应该如何设计这个?

回答by Ernest Friedman-Hill

You can make each class separately a singleton, and make the base class abstract. Not sure what's the debate -- just that singletons, in general, aren't a great idea?

您可以将每个类单独设为单例,并使基类抽象。不知道有什么争论——一般来说,单身不是一个好主意?

回答by Apalala

Use the Abstract factory pattern. Have a separate class with methods to retrieve the singletons, and let it hold the references to the singletons in instance variables or in a map.

使用抽象工厂模式。有一个单独的类,其中包含检索单例的方法,并让它在实例变量或映射中保存对单例的引用。

You may not want the increased complexity, but frameworks like Springwere created to solve these kind of issues (among others).

您可能不希望增加复杂性,但是创建了像Spring这样的框架来解决这类问题(以及其他问题)。

It seems that Pico Containeris alive and well, and it may be the simplest while still solid solution. Look at the inversion of controltopics, and let the framework inject the singletons where you need them.

Pico Container似乎还活着,而且它可能是最简单但仍然是可靠的解决方案。看看控制主题的反转,让框架在你需要的地方注入单例。

In short, don't try to make the singletons manage access to themselves. Delegate that on something else.

简而言之,不要试图让单身人士管理对自己的访问。把它委托给别的东西。

There's nothing inherently wrong in having singleton classes with complex inheritance. In fact, class hierarchies with private constructors (no instances) are very useful in many situations. You just have to decide how you want to manage the two important aspects of singletons: creation, and access.

拥有具有复杂继承的单例类并没有本质上的错误。事实上,具有私有构造函数(无实例)的类层次结构在许多情况下都非常有用。您只需要决定如何管理单身人士的两个重要方面:创建和访问。

回答by blong824

I don't know if you need an example but I gave it a try. Without knowing any of your details this example is very vague. I am also here to learn so let us know what you end up implementing.

我不知道你是否需要一个例子,但我试了一下。在不知道您的任何详细信息的情况下,此示例非常模糊。我也在这里学习,所以让我们知道你最终实施了什么。

The Base class:

基类:

  public abstract class BaseClass {

        public void someMethod() {
            System.out.println("base class hello: " + this);
        }

        public abstract void someOtherMethod(String value);
    }

One of the subclasses:

子类之一:

public class SubClassOne extends BaseClass {

    private static SubClassOne instance;

    private SubClassOne() {}

    public static SubClassOne getInstance() {
        if (instance == null) {
            instance = new SubClassOne();
        }
        return instance;
    }

    public void someOtherMethod(String value) {
        someMethod();
        System.out.println("sub class hello: " + value + " " + this);
    }

    public static void main(String[] args) {
        SubClassOne one = SubClassOne.getInstance();
        SubClassOne two = SubClassOne.getInstance();
        SubClassOne three = SubClassOne.getInstance();
        SubClassOne four = SubClassOne.getInstance();
        one.someOtherMethod("one");
        two.someOtherMethod("two");
        three.someOtherMethod("three");
        four.someOtherMethod("four");
    }
}

回答by Adrian

I had a similar requirement: I had multiple cache maps with repeating methods and members, so I've created an abstract class like:

我有一个类似的要求:我有多个带有重复方法和成员的缓存映射,所以我创建了一个抽象类,如:

public abstract class AbstractCache<T> {

    protected final Map<String, T> cache;

    protected AbstractCache() {
        this.cache = getDefaultExpiringMap(TimeUnit.HOURS.toMillis(4));
    }

    public Map<String, T> getCache() {
        return cache;
    }

    public T getAll(String id) {
        return cache.get(id);
    }
}

Then I've extended this class and created a singleton instance:

然后我扩展了这个类并创建了一个单例实例:

public final class FooCache extends AbstractCache<Set<Integer>> {

    public static final FooCache INSTANCE = new FooCache();

    private FooCache() {
        super();
    }

    public void add(String fooId, Integer value) {
        cache.computeIfAbsent(fooId, k -> new HashSet<>()).add(value);
    }
}

And the usage:

以及用法:

public static void main(String[] args) {
    FooCache.INSTANCE.add("a", 1);
    System.out.println(FooCache.INSTANCE.getAll("a"));
}

回答by inor

Inheritance is not the only way to re-use common functionality. Containment may be preferable in the general case. Consider the following solution in which class A and B are the singletons, and the common functionality is in class AB, but instead of extending AB, both A and B use an instance of AB which is a singleton itself.

继承并不是重用通用功能的唯一方法。在一般情况下,遏制可能更可取。考虑以下解决方案,其中 A 类和 B 类是单例,公共功能在 AB 类中,但 A 和 B 都使用 AB 实例,而不是扩展 AB,而 AB 实例本身就是单例。

class AB { //common functionality of A and B
   //singleton pattern here
   //common data and functionality here
}
class A {
   private AB ab = AB.getInstance();
   //singleton pattern here
   //unique functionality and data of A

   //to use any of the functionality in AB delegate to member ab
}

class B is similar to A.

B类与A类相似。

in this solution there is a single instance of every data and functionality of both A and B (and AB)

在此解决方案中,A 和 B(和 AB)的每个数据和功能都有一个实例

Note that if clients of A and B need to access the common public methods in AB, then AB, A and B should implement an interface of those public methods, and A and B implementation should delegate the call to ab.

请注意,如果A和B的客户端需要访问AB中的公共公共方法,则AB、A和B应实现这些公共方法的接口,并且A和B实现应将调用委托给ab。



The solution proposed by Ernest below, may be a shortcut in some situations, but in general is a wrong solution.

下面由 Ernest 提出的解决方案,在某些情况下可能是捷径,但通常是错误的解决方案。

To explain why Ernest's solution may be wrong, let's describe that solution in a different way. Suppose i have a singleton class A and i discover that i need to write another singleton class B, but i need some of the functionality of A in B. So i factor out the common data and functionality of A into an abstract class AB and make both A and B extend AB. The reason why it's wrong, in general, is because this solution takes a subset of the data and functionality which is supposed to exist only once, and places it in a sub-class (AB), effectively and potentially duplicating it in every sub-class that will be created. Now, after getting an instance of A and an instance of B, you have two instances of the subset data and functionality in AB.

为了解释为什么 Ernest 的解决方案可能是错误的,让我们以不同的方式描述该解决方案。假设我有一个单例类 A 并且我发现我需要编写另一个单例类 B,但是我需要 B 中 A 的一些功能。所以我将 A 的公共数据和功能分解为抽象类 AB 并制作A 和 B 都扩展了 AB。之所以错误,通常是因为该解决方案采用了应该只存在一次的数据和功能的子集,并将其放在子类 (AB) 中,有效地并可能在每个子类中复制它将创建的类。现在,在获得 A 的实例和 B 的实例后,您在 AB 中有两个子集数据和功能的实例。

If for example, the common functionality placed in the base class writes some initial data to the file named "myData", then both of your singletons will execute this code even though it was only meant to be executed once, and when the later executes it it will wipe out the file created by the former.

例如,如果放置在基类中的公共功能将一些初始数据写入名为“myData”的文件,那么您的两个单例都会执行此代码,即使它只打算执行一次,并且当后者执行它时它将清除前者创建的文件。

Therefore, in general, the solution described here does not use inheritance, and ensures that a singleton encapsulates the common functionality as well as the singleton classes that use it.

因此,总的来说,这里描述的解决方案不使用继承,并确保单例封装了通用功能以及使用它的单例类。

回答by J T

I'm not an expert in Java, so I don't know if this is technically legal Java code (perhaps another poster can comment):

我不是 Java 专家,所以我不知道这在技术上是否合法的 Java 代码(也许另一位发帖者可以评论):

Make the base classes inherit from a generic class Singleton.

使基类从泛型类 Singleton 继承。

Example:

例子:

class Singleton<T> {

    protected Singleton(); //constructor

    private static T _instance;

}

class DerivedOne extends Singleton<DerivedOne>{

    protected DerivedOne(){} //constructor
}

class DerivedTwo extends Singleton<DerivedTwo>{

    protected DerivedTwo(){} //constructor
}