将单例用于不可变的无参数 类 不好吗?
Is it bad to use Singletons for immutable no-argument classes?
我现在正在做一个小的 Java 项目,同时在那里创建了多个 classes,它们代表某种常量行为,例如用作默认值 return 其他方法的价值。
现在所有这些的共同点是,它们是完全不可变的,并且它们只有一个无参数构造函数。这意味着创建 class 的多个实例将始终产生相同的对象。
每次使用这些 classes 时只创建一个新实例是否更好,或者这是使用单例模式的可接受情况?
在您的情况下,使用单例模式是有意义的。对于简单的应用程序,您可以使用静态方法 return 实例。如果您在提供控制反转的环境中工作,例如 Spring,IOC 框架将为您处理单例。
如果公开修改不可变状态的方法 class,您必须始终 return 此 class 的新实例。
假设您有一个小项目和不可变 类 用作默认 return 值,让我们考虑一下单例的优缺点。
在这种情况下单例的优点:
- 应用程序构造一个对象而不是多个;
请记住,通常构造一个新对象在 Java 中是一种廉价操作。
如果您的对象寿命不长,GC 将收集它们而不会对您的应用程序的性能产生重大影响。如果您不必每秒创建数千个此类对象,则此方法适用。
缺点:
更多代码读写;
虽然编写 getInstance()
方法可能看起来没什么大不了的,但与您一起工作的其他人(可能)会花一些时间探索 getInstance()
在修复错误或理解某些业务逻辑时的真正作用。我见过许多令人惊讶的 getInstance()
方法,尽管它们有一个传统的名称。
潜在的并发问题;
即使您的项目很小,您也可能希望使用多个线程。在这种情况下,您必须将 getInstance()
编写为同步方法,引入 double-checked locking,使用枚举或其他方式。
即使您知道这种特殊性,也不能保证其他开发人员不会犯错误。
所以我认为没有唯一的正确答案,这取决于你如何看待你的项目未来的发展。
即使是小项目,我也会努力坚持Dependency Inversion Principle, i.e. a class does not instantiate its own dependencies, but declares them, usually in a constructor. That way, each class can be developed and tested in isolation, while being tied together with everything else using either a framework like Spring or Guice or manual dependency injection。使用这样的设置,您可能只有一个 class 的实例,但您不需要实现 classic 单例模式。
创建一个小项目就是要做出正确的权衡:您不想过度设计,但也不想编写不可扩展和不可维护的代码。所以不,几乎从来没有一个有效的借口来使用单例模式(使用 classloader 保护单例)。
我现在正在做一个小的 Java 项目,同时在那里创建了多个 classes,它们代表某种常量行为,例如用作默认值 return 其他方法的价值。
现在所有这些的共同点是,它们是完全不可变的,并且它们只有一个无参数构造函数。这意味着创建 class 的多个实例将始终产生相同的对象。
每次使用这些 classes 时只创建一个新实例是否更好,或者这是使用单例模式的可接受情况?
在您的情况下,使用单例模式是有意义的。对于简单的应用程序,您可以使用静态方法 return 实例。如果您在提供控制反转的环境中工作,例如 Spring,IOC 框架将为您处理单例。
如果公开修改不可变状态的方法 class,您必须始终 return 此 class 的新实例。
假设您有一个小项目和不可变 类 用作默认 return 值,让我们考虑一下单例的优缺点。
在这种情况下单例的优点:
- 应用程序构造一个对象而不是多个; 请记住,通常构造一个新对象在 Java 中是一种廉价操作。 如果您的对象寿命不长,GC 将收集它们而不会对您的应用程序的性能产生重大影响。如果您不必每秒创建数千个此类对象,则此方法适用。
缺点:
更多代码读写; 虽然编写
getInstance()
方法可能看起来没什么大不了的,但与您一起工作的其他人(可能)会花一些时间探索getInstance()
在修复错误或理解某些业务逻辑时的真正作用。我见过许多令人惊讶的getInstance()
方法,尽管它们有一个传统的名称。潜在的并发问题; 即使您的项目很小,您也可能希望使用多个线程。在这种情况下,您必须将
getInstance()
编写为同步方法,引入 double-checked locking,使用枚举或其他方式。 即使您知道这种特殊性,也不能保证其他开发人员不会犯错误。
所以我认为没有唯一的正确答案,这取决于你如何看待你的项目未来的发展。
即使是小项目,我也会努力坚持Dependency Inversion Principle, i.e. a class does not instantiate its own dependencies, but declares them, usually in a constructor. That way, each class can be developed and tested in isolation, while being tied together with everything else using either a framework like Spring or Guice or manual dependency injection。使用这样的设置,您可能只有一个 class 的实例,但您不需要实现 classic 单例模式。
创建一个小项目就是要做出正确的权衡:您不想过度设计,但也不想编写不可扩展和不可维护的代码。所以不,几乎从来没有一个有效的借口来使用单例模式(使用 classloader 保护单例)。