Java:[全局方法访问]单实例枚举vs按需对象构造vs静态

Java:[全局方法访问]单实例枚举vs按需对象构造vs静态,java,static,enums,object-reference,object-construction,Java,Static,Enums,Object Reference,Object Construction,我想创建一个包含几个方法的类,这些方法可以在包中的任何位置使用。在阅读了enum自动提供了安全的实例化、序列化和防止在enum外部实例化后,我选择将enum与单个实例一起使用。我相信这是创造单身的最简单和安全的方式。但我的上司回来说这是肮脏的编程。真的吗?有人知道使用枚举代替对象构造和使用类传递引用的缺点吗?枚举何时初始化 public enum Myenum { INSTANCE; public void init(...) {..initialize local varia

我想创建一个包含几个方法的类,这些方法可以在包中的任何位置使用。在阅读了enum自动提供了安全的实例化、序列化和防止在enum外部实例化后,我选择将enum与单个实例一起使用。我相信这是创造单身的最简单和安全的方式。但我的上司回来说这是肮脏的编程。真的吗?有人知道使用枚举代替对象构造和使用类传递引用的缺点吗?枚举何时初始化

public enum Myenum {
    INSTANCE;

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

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

vs

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

enum是否隐式地提供了依赖项注入的好处?(即,可以在包内的任何地方访问Myenum的method1、method2,而无需担心实例创建)

我需要的enum的另一个特性是不能在enum外部重写enum内部的方法


我是否遗漏了一些明显的缺点?

一个
enum
向其他程序员发出了一个语义信号,即它是一个具有一系列可能值的类型,您可以在switch语句中进行检查。然而,与人们通常在Java中使用的大多数其他模式相比,Enum可以被看作是一种更好的单例模式实现

如果您确定要使用单例模式,那么使用
enum
可能没问题。然而,有些模式往往更灵活,更易于单元测试,更可靠,等等。如果有一天你决定不再希望它成为一个单独的模式,会怎么样?如果希望在数据库中进行某些更改时可以刷新,该怎么办?使用任何单例模式都会将您锁定在单例表示中,并使将来进行类似更改变得更加困难

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

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

摘录:

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

  • 他们违反了单一责任原则:因为他们控制着自己的创作和生命周期

  • 它们内在地导致代码紧密耦合。这使得在许多情况下,在测试中伪造它们相当困难

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


  • 在实践中查看Java并发及其静态单例模式。看起来是这样的:

    public class ResourceFactory {
        private static class ResourceHolder {
            public static Resource resource = new Resource();
        }
    
        public static Resource getResource() {
            return ResourceHolder.resource;
        }
    }
    
    它是安全的,因为静态是如何/何时初始化的,可能与枚举单例技巧是安全的原因相同


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

    那个人解释了为什么他们认为它很脏吗?你能问他们吗?不,他有点“无论你的工作有多好,我都有足够的经验不同意你的意见”。他说的一件事是,这是一种干净方法的替代方法(创建一个对象并传递对它的引用)。我的想法是,如果enum隐式地提供了许多我上面提到的东西,为什么不直接使用它呢?即使在我的例子中我不需要它的一些好处(序列化)。这样使用它有什么缺点吗?除非您在依赖项注入中使用控制反转容器,否则您的
    enum
    解决方案可能是最好的。测试
    enum
    解决方案并不容易,因为您无法控制进入构造函数的内容(如果有的话)。我的目标是防止不必要的引用传递和保护实例化。init只能被调用一次。我是如何多次实例化的?你不是。我指的是我自己。依赖注入是一个答案,但它需要增加一个框架和一些复杂的代码。Enum是一种简单的方法,它隐式地提供了这些东西,而不需要任何额外的框架。我的目标是保护实例化和不必要的引用传递。enum方法受到保护,不会被覆盖。@yalkris:依赖项注入是一种我发现效果很好的模式,它可以在没有框架的情况下使用,尽管框架可以提供帮助。但它确实倾向于一个全有或全无的命题:一旦你在一个地方开始使用这个模式,你就必须在任何地方使用它。工厂模式可以给您带来许多相同的好处,而不会如此普遍。但你比我更了解你的代码基础:如果你想要一个单身汉,我该和谁争论呢?;-)好发现。所以问题不一定是“enum-as-a-singleton”模式,而是通常的“singleton”模式。它服务于我使用singleton(可以在包中的任何地方访问的全局方法)的目标之一,但是使用singleton作为传递引用的替代方法有相同或更多的缺点。
    public class Myclass {
        public static void init(...) {...initialize local variables...}
    
        public static method1 (...) {...}
        public static method2 (...) {...}
    }
    
    public class ResourceFactory {
        private static class ResourceHolder {
            public static Resource resource = new Resource();
        }
    
        public static Resource getResource() {
            return ResourceHolder.resource;
        }
    }