【问题标题】:How can I have a Singleton that's derived from an abstract base type in Java?我怎样才能拥有一个从 Java 中的抽象基类型派生的单例?
【发布时间】:2009-05-15 15:47:19
【问题描述】:

我有一些用作单例的类。它们共享一些基本功能,并从通常不用作 Singleton 的库中扩展相同的祖先。

如果我将通用功能放在继承自共同祖先的基类中,我会得到一个实例化没有意义的类,因此我将其抽象化。此外,因为这些类都用作单例,所以它们都应该有一个 init() 和一个 getInstance() 方法,它们都是静态的。所有的构造函数当然都是非公开的。

现在,由于 static 是抽象方法的非法修饰符,因此以下内容不起作用,尽管这正是我想要的:

class Base extends LibraryClass {
    protected Base() {
        // ... constructor
    }

    // ... common methods

    // ILLEGAL!
    public static abstract void init();
    public static abstract <T extends Base>T getInstance();
}

class A extends Base {
    private static A _INSTANCE;

    private A() {
        super();
    }

    public static void init() {
        _INSTANCE = new A();
    }

    public static A getInstance() {
        return _INSTANCE;
    }
}

我可以忽略基类中的非法行并完成它。但是如何表达 Base 的每个子节点必须有这些方法呢?

【问题讨论】:

    标签: java inheritance singleton


    【解决方案1】:

    这在 Java 中是不可能的。不能强制存在static 方法;既不是通过abstract 也不是通过使用interface

    我的解决方案是以某种方式使用 IoC:我为单例创建了一个工厂类。它会将单身人士保存在地图中。关键是班级。这样,我可以说:

    A singleton = Factory.create (A.class);
    

    这种设计的主要优点:我可以创建一个Factory.replace() 方法,其中测试用例可以覆盖单例。

    【讨论】:

    • 为什么我们在 Java 中已经有了 Static 或 Final 的情况下还需要 Singleton?迫使我们采用“Singleton”而不是“Static,Final”的主要辞职/原因是什么?虽然为了实现单例,我们使用静态。我无法理解这个谜题。请通过您的 cmets。
    • static final 用于急切创建的常量。单例通常是惰性创建的(仅在需要时)。此外,静态最终不允许用模型替换“常量”。因此,它们使测试变得困难甚至不可能。
    【解决方案2】:

    处理将单例语义添加到可能不方便正确添加语义的类的常见方法是在包装类中实现单例功能。例如:

    public class UsefulThing {
    
    }
    
    public final class SingletonOfUsefulThing {
        private static UsefulThing instance;
    
        private SingletonOfUsefulThing() {}
    
        public UsefulThing getInstance() {
            if (instance == null) {
                instance = new UsefulThing(); 
            }
    
            return instance;
        }
    }
    

    这允许您为类提供一些主要的单例好处,而不会产生在类中实现单例语义直接迫使您处理的一些后果,并为更改您的类的特定类型留出一些空间'重新暴露为单例(例如,通过使用工厂创建实例,而不是 new

    【讨论】:

    • 我猜你的getInstance()方法也应该是static
    【解决方案3】:

    你不能表示子类有特定的静态方法。

    事实上,不需要这样做,因为静态方法只会在子类(您的示例中为A.init()A.getInstance())上直接调用,而永远不会通过对基类的引用(即静态方法不支持多态性)。

    【讨论】:

      【解决方案4】:

      你为什么不一路走下去,让你的工厂(在基类中)传入一个参数,指示你希望它返回哪个子类。这样做有很多优点,而缺点很少。

      您尝试这样做的方式没有多大意义,因为静态方法与普通方法处理继承的方式不同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-20
        • 1970-01-01
        • 2018-08-17
        • 1970-01-01
        • 2022-12-14
        • 1970-01-01
        • 1970-01-01
        • 2011-01-07
        相关资源
        最近更新 更多