正确的单例设计? [复制]

Posted

技术标签:

【中文标题】正确的单例设计? [复制]【英文标题】:Proper singleton design? [duplicate] 【发布时间】:2011-09-23 19:18:44 【问题描述】:

可能重复:Efficient way to implement singleton pattern in Java

我有一个单例类,它充当我的应用程序的状态保护程序。例如,如果我有一个包含一些数据的视图,我只需将数据打包到一个已保存的状态可序列化对象中,然后将其传递给我的单例以便稍后检索。这一切看起来自然而恰当,但我已经偏离了Wiki 上的单例示例。我没有一个 get 实例方法可以让我检索实例并通过实例调用方法,而是将每个方法都设置为静态并静态使用该类。

这是不好的形式吗?有没有性能损失?

感谢您的任何提示~Aedon

【问题讨论】:

参见例如here 【参考方案1】:

如果静态使用满足您的需求,我看不出它有什么坏处。

唯一的缺点是它的灵活性稍差。如果将其设计为实际的单例,则可以有一个用于管理状态的接口,并针对特定情况实例化特定的实现。然后可以将该对象作为参数传递到您的应用程序中。

使用严格的静态类,没有要传递的对象,因此您必须求助于传递 Class 对象并通过该接口访问函数。

当然,所有这些只有在有可能超出您当前班级的合理能力时才有意义。

【讨论】:

嗯,很有趣。谢谢你。我全部采用静态的原因之一是为了便于访问(这是一种说惰性设计的奇特方式)。如果我更深入地研究一个应用程序并且我意识到访问某些数据有点麻烦,我发现只使用全静态类会更容易。 嗯,让它成为一个单例应该只为每次使用添加一行代码。即代替“foo=Single.getFoo();”你会有“Single single=Single.getIntance(); foo=single.getFoo();”。如果您只需要单例中的一个字段,它只会使一行稍长一些,例如“foo=Single.getInstance().getFoo();”对于长期灵活性而言,这似乎是一个相当小的代价。【参考方案2】:

是的,它被认为是错误的形式。

Java 中的静态类存在许多问题,使它们难以使用。例如,您不能实现接口。此外,如果您需要再次使其成为常规单例(或者需要使其成为非单例(这种情况经常发生)),则必须重写与其交互的每一行代码。

【讨论】:

我会争辩说,根据经验,更改为非单例无论如何都需要重构每一行,因为访问单例的最常见方式是 MySingleton.getInstance().someMethod()。并不是说我对其余部分提出异议,只是那一点。【参考方案3】:

是的,仅使用静态方法和变量不是面向对象的方式。 单身人士大多被认为是一种不好的做法。但是,我承认它们有时非常有用。这是一个如何创建有效且功能正常的 Singleton 类的简单示例。请注意,还有其他方法,但这是最常见的方法之一...

public class Singleton 
   private static final Singleton uniqueInstance;

   public static synchronized Singleton getInstance() 
     if (Singleton.uniqueInstance == null) 
       Singleton.uniqueInstance = new Singleton();
     
     return Singleton.uniqueInstance;
   

   //other methods go here...

   @Override
   protected Singleton clone() throws CloneNotSupportedException() 
     throw new CloneNotSupporedException("cloning of singleton is not supported");
   

   //hide constructor for others to see
   private Singleton() 
   

干杯,P

【讨论】:

多余的代码发布... 谢谢,但我知道单例是如何完成的,我只是好奇静态的做事方式是否效率较低。 如果@AedonEtLIRA 不确定如何编写单例并且只使用静态方法,那这有什么必要? @AedonEtLIRA 好的 - 我没有完全从你的问题中得到这个...... :) 干杯【参考方案4】:

Use Enum instead of Singleton。这是最安全的方式。

【讨论】:

您能不能说得更笼统一些?而且你的措辞都是错误的。 @little bunny foo foo - 同意。 @Boris - 我不完全确定我是否跟随。 @AedonEtLIRA,@Boris 想说的是,enum 单例模式是首选的单例实现。 -1 这可能是真的,但这是评论(关于重复),而不是新答案。 @Little bunny foo foo - 我明白了。感谢您的澄清。【参考方案5】:

它被认为是不好的形式,因为它不是面向对象的风格。无论如何,许多人认为单身人士的形式不佳。坦率地说,它对你想要做的事情来说效果很好。除非您要提交此内容以供审核或评估,否则我将不理会它。

作为静态类,性能可能会更好。

【讨论】:

就我个人而言,我从来没有被“它很糟糕,因为它不是面向对象的”的论点所说服。我的反应是,“那又怎样?”每当某事的理由是“因为所有专家都这么说”或“因为教科书是这么说的”时,我认为这意味着“我真的不知道为什么”。【参考方案6】:

添加到@Boris 的评论中,如果您只需要一个实用程序类,那么使用枚举会更简单

public enum Utility 
    ; // no instances
    public static Object myStaticMethod(Object ... args)  

如果你有一个接口要实现,那么这个单例是有意义的。请注意,您可以使用枚举创建多个单例

public enum Callables implements Callable<String> 
    HELLO 
         public String call()  return "Hello"; 
    , 
    WORLD 
         public String call()  return "World"; 
    

注意:HELLO 和 WORLD 共享一个超类 Callables,但实际上有不同的类。

【讨论】:

以上是关于正确的单例设计? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中正确创建线程安全的单例工厂? [复制]

高并发下线程安全的单例模式

python中的单例设计模式

基于unity的单例设计模式写法

java的单例设计模式

python中的单例设计模式