1

我想用几个方法创建一个类,可以在包内的任何地方使用。在阅读了枚举自动提供安全实例化、序列化和防止在枚举之外实例化的保护后,我选择将枚举与单个实例一起使用。我相信这是创建单例最简单、最安全的方法。但我的上司回来说这是肮脏的编程。真的吗?有谁知道使用枚举而不是对象构造和使用类传递引用的缺点?枚举什么时候初始化?

public enum Myenum {
    INSTANCE;

    public void init(...) {..initialize local variables...}

    public method1 (...) {...}
    public method2 (...) {...}
}

对比

public class Myclass {
    public Myclass(...) {...initialize local variables...}

    public method1 (...) {...}
    public method2 (...) {...}
}

对比

public class Myclass {
    public static void init(...) {...initialize local variables...}

    public static method1 (...) {...}
    public static method2 (...) {...}
}

在我看来,使用第二种方法的缺点是,在我需要在对象构造时使用方法和同步问题的任何地方都需要 Myclass 的对象引用。在我的案例中,我并没有真正使用 enum 的序列化优势。

枚举是否隐含地提供了依赖注入的好处?(即可以在包内随处访问Myenum的method1、method2,不用担心创建实例)

我需要的枚举的另一个特性是枚举内部的方法不能在它之外被覆盖。

我在这里错过了一些明显的缺点吗?

4

3 回答 3

2

Anenum给其他程序员一个语义信号,表明它是一个具有一系列可能值的类型,您可以检查这些值,例如,在 switch 语句中。但是,有许多令人信服的理由说明枚举可以被视为比人们通常在 Java 中使用的大多数其他模式更好的单例模式实现。

如果您确定要使用单例模式,那么使用 anenum可能是可以的。但是,有些模式往往更灵活、可单元测试、SOLID 等。如果有一天您决定不再希望它成为单例模式怎么办?如果您希望在数据库中进行某些更改时它可以刷新怎么办?使用任何单例模式都会将您锁定在单例表示中,并使将来更难进行此类更改。

工厂模式比单例模式更灵活,但在我看来,最好的模式是使用依赖注入。您可以单例绑定您的类型以避免重新实例化它的成本,但类型本身(及其消费者)不需要绑定到特定的生命周期或模式。

于 2014-06-25T19:49:48.670 回答
0

查看 Java Concurrency In Practice 及其静态单例模式。它看起来像这样:

public class ResourceFactory {
    private static class ResourceHolder {
        public static Resource resource = new Resource();
    }

    public static Resource getResource() {
        return ResourceHolder.resource;
    }
}

由于静态的初始化方式/时间,它是安全的,这可能与 Enums 单例技巧是安全的原因相同。

在 JCIP 的示例中,它返回一个东西,但是您可以添加所有您想要使用的静态方法,无论您想要在 ResourceHolder 中初始化多少变量。并且不需要 init() 调用。

于 2014-06-26T19:22:48.890 回答
0

我在这里找到了一个答案,为什么创建一个全局可访问的模式是不好的,而不是传递引用。

摘抄:

  1. 它们通常用作全局实例,为什么这么糟糕?因为您在代码中隐藏了应用程序的依赖项,而不是通过接口公开它们。使某些东西全局化以避免传递它是一种代码味道。

  2. 它们违反了单一责任原则:因为它们控制着自己的创建和生命周期。

  3. 它们本质上会导致代码紧密耦合。在许多情况下,这使得在测试中伪造它们相当困难。

  4. 它们在应用程序的生命周期内携带状态。测试的另一个打击,因为您最终可能会遇到需要订购测试的情况,这对于单元测试来说是一个很大的禁忌。为什么?因为每个单元测试都应该相互独立。

于 2014-06-26T19:10:19.770 回答