当前位置:  开发笔记 > 编程语言 > 正文

什么时候应该使用单例模式而不是静态类?

如何解决《什么时候应该使用单例模式而不是静态类?》经验,为你挑选了5个好方法。

在决定使用单例与静态类之间进行设计考虑.在这样做时,你有点被迫对比这两者,所以无论你能想出什么对比,都有助于展示你的思考过程!此外,每位采访者都喜欢看到说明性的例子.:)



1> Tobias..:

单身人士可以实现接口并从其他类继承.

单身人士可以懒惰加载.只有在实际需要的时候.如果初始化包括昂贵的资源加载或数据库连接,这非常方便.

单身人士提供了一个实际的对象.

单身人士可以扩展到工厂.幕后的对象管理是抽象的,因此它可以更好地维护并产生更好的代码.


"单例可以延迟加载" - 在C#中,静态构造函数仅在第一次引用静态成员时调用.在PHP中,您可以使用自动加载仅在第一次使用该类时运行它.
请看这个链接:http://codeofdoom.com/wordpress/2008/04/20/how-and-when-to-use-singleton-classes/

2> TrueWill..:

如何"避免两者"?单身人士和静态课程:

可能会介绍全球状态

紧密耦合到其他多个类

隐藏依赖项

可以使单元测试类孤立起来很困难

相反,请查看依赖注入和控制容器库的反转.一些IoC库将为您处理生命周期管理.

(与往常一样,有一些例外,例如静态数学类和C#扩展方法.)


如果你想给你的单身人士一个适当的埋葬,请访问http://www.singletonfuneralservice.com/

3> xanadont..:

我认为唯一的区别是语法:MySingleton.Current.Whatever()vs MySingleton.Whatever().正如大卫所说,国家在任何一种情况下最终都是"静态的".


编辑:埋葬旅从digg过来......无论如何,我想到了一个需要单身的情况.静态类不能从基类继承,也不能实现接口(至少在.Net中它们不能).因此,如果您需要此功能,则必须使用单例.



4> newdayrising..:

关于这个问题,我最喜欢的讨论之一就在这里(原始站点下来,现在链接到Internet Archive Wayback Machine.)

总结Singleton的灵活性优势:

Singleton可以很容易地转换成工厂

可以轻松修改Singleton以返回不同的子类

这可以导致更易于维护的应用程序



5> Tim Williscr..:

带有静态变量的静态类有点像黑客.

/**
 * Grotty static semaphore
 **/
 public static class Ugly {

   private static int count;

   public synchronized static void increment(){
        count++;
   }

   public synchronized static void decrement(){
        count--;
        if( count<0 ) {
            count=0;
        }
   }

   public synchronized static boolean isClear(){
         return count==0;    

    }
   }

具有实际实例的单例更好.

/**
 * Grotty static semaphore
 **/
 public static class LessUgly {
   private static LessUgly instance;

   private int count;

   private LessUgly(){
   }

   public static synchronized getInstance(){
     if( instance==null){
        instance = new LessUgly();
     }
     return instance;
   }
   public synchronized void increment(){
        count++;
   }

   public synchronized void decrement(){
        count--;
        if( count<0 ) {
            count=0;
        }
   }

   public synchronized boolean isClear(){
         return count==0;    

    }
   }

该州仅在该实例中.

因此,稍后可以修改单例以执行池化,线程局部实例等.并且所有已编写的代码都不需要更改以获得好处.

public static class LessUgly {
       private static Hashtable session;
       private static FIFO freePool = new FIFO();
       private static final POOL_SIZE=5;
       private int count;

       private LessUgly(){
       }

       public static synchronized getInstance(){
         if( session==null){
            session = new Hashtable(POOL_SIZE);
            for( int i=0; i < POOL_SIZE; i++){
               LessUgly instance = new LessUgly();  
               freePool.add( instance)
            }
         }
         LessUgly instance = session.get( Session.getSessionID());
         if( instance == null){
            instance = freePool.read();
         }
         if( instance==null){
             // TODO search sessions for expired ones. Return spares to the freePool. 
             //FIXME took too long to write example in blog editor.
         }
         return instance;
       }     

可以使用静态类执行类似的操作,但间接调度中将存在每个调用的开销.

您可以获取实例并将其作为参数传递给函数.这使代码可以指向"正确"的单例.我们知道你只需要其中一个...直到你不需要它.

最大的好处是有状态的单身人士可以成为线程安全的,而静态的单人则不能,除非你把它修改成一个秘密的单身人士.

推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有