Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 什么时候应该使用单例模式而不是静态类?_Design Patterns - Fatal编程技术网

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

Design patterns 什么时候应该使用单例模式而不是静态类?,design-patterns,Design Patterns,在决定使用静态类还是静态类时,请列出设计注意事项。在这样做的过程中,你被迫将两者进行对比,因此,无论你能想出什么样的对比,都有助于展示你的思维过程!此外,每个面试官都喜欢看到说明性的例子 当单个类需要状态时。单例保持全局状态,静态类不保持全局状态 例如,在注册表类周围创建一个助手:如果您有可更改的配置单元(HKey Current User vs.HKey Local Machine),您可以: RegistryEditor editor = RegistryEditor.GetInstance

在决定使用静态类还是静态类时,请列出设计注意事项。在这样做的过程中,你被迫将两者进行对比,因此,无论你能想出什么样的对比,都有助于展示你的思维过程!此外,每个面试官都喜欢看到说明性的例子

当单个类需要状态时。单例保持全局状态,静态类不保持全局状态

例如,在注册表类周围创建一个助手:如果您有可更改的配置单元(HKey Current User vs.HKey Local Machine),您可以:

RegistryEditor editor = RegistryEditor.GetInstance();
editor.Hive = LocalMachine

现在,对该单例的任何进一步调用都将在本地机器配置单元上运行。否则,使用静态类,每次都必须指定本地机器配置单元,或者使用类似于
ReadSubkeyFromLocalMachine

的方法。我认为唯一的区别是语法:MySingleton.Current.Whatever()与MySingleton.Whatever()。正如大卫所提到的,无论哪种情况,国家最终都是“静态的”


编辑:伯里旅从迪格过来。。。不管怎样,我想到了一个需要单身汉的案子。静态类不能从基类继承,也不能实现接口(至少在.Net中不能)。所以,如果您需要此功能,那么必须使用单例。

如果“静态类”指的是只有静态变量的类,那么它们实际上可以维护状态。我的理解是唯一的区别是你如何访问这个东西。例如:

MySingleton().getInstance().doSomething();

MySingleton.doSomething();

<> Py> MyStLon的内部结构将明显不同,但线程安全问题除外,它们对客户端代码的执行都是相同的。

< P>不应该使用单体(除非你考虑一个没有可变状态的类)。“静态类”应该没有可变状态,除了线程安全缓存等


几乎任何一个单独的例子显示了如何不去做它。

< P>如果一个单独的东西是你可以处理的,在它之后清理,你可以考虑它是一个有限的资源(即只有1个),你不需要所有的时间,并且在分配时有某种内存或资源成本。 与包含静态状态字段的静态类相比,使用单例时,清理代码看起来更自然


但是,无论哪种方式,代码看起来都是一样的,因此如果您有更具体的原因询问,也许您应该详细说明。

这两者可能非常相似,但请记住,真正的单例本身必须实例化(授予,一次)然后提供服务。返回
mysqli
实例的PHP数据库类并不是一个真正的单例(有些人称之为单例),因为它返回的是另一个类的实例,而不是将实例作为静态成员的类的实例


因此,如果您正在编写一个新类,并且计划在代码中只允许一个实例,那么您不妨将其作为一个单例来编写。可以将其视为编写一个简单的jane类并添加到其中以满足单一实例化需求。如果您使用的是无法修改的其他类(如
mysqli
),则应该使用静态类(即使您没有在其定义前面加上关键字)。

单例更灵活,当您希望实例方法根据某些上下文返回Singleton类型的不同具体子类时,这非常有用。

静态类不能作为参数传递;单例实例可以是。正如其他答案中提到的,注意静态类的线程问题


rp

单例可以有构造函数和析构函数。根据您的语言,构造函数可能在第一次使用singleton时自动调用,如果根本不使用singleton,则永远不会调用。静态类不会有这样的自动初始化

一旦获得对单例对象的引用,它就可以像任何其他对象一样使用。如果前面存储了对单例的引用,则客户端代码甚至可能不需要知道其使用单例:

Foo foo = Foo.getInstance();
doSomeWork(foo); // doSomeWork wont even know Foo is a singleton

当您选择放弃单例模式而选择真正的模式(如IoC)时,这显然会使事情变得更容易。

当您需要在运行时计算一些您可能在编译时计算的东西时,如查找表,请使用单例模式。

将单例想象为一种服务。它是一个提供特定功能集的对象。例如

ObjectFactory.getInstance().makeObject();
对象工厂是执行特定服务的对象

相反,一个充满静态方法的类是您可能想要执行的操作的集合,组织在一个相关的组(类)中。例如


这里的StringUtils示例是可以应用于任何地方的功能集合。singleton factory对象是一种特定类型的对象,具有明确的责任,可以在需要时创建和传递。

关于这个问题,我最喜欢的讨论之一是(原始站点已关闭,现在链接到。)

要总结单身人士的灵活性优势,请执行以下操作:

  • 单件可以很容易地转换 进工厂
  • 一个单身汉可以很容易地 修改为返回不同的 子类
  • 这可以产生一个更易于维护的应用程序

静态类在运行时实例化。这可能很耗时。只有在需要时才可以实例化Singleton。

我认为,当您必须构建一个昂贵的资源池(如数据库连接)时,Singleton比静态类更有意义。如果没有人使用池,您就不会对创建池感兴趣(静态类意味着您在加载类时要做代价高昂的工作)。

加载静态变量的静态类有点麻烦

/**
 * 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静态信号量
**/
/**
 * 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<String,LessUgly> session;
       private static FIFO<LessUgly> freePool = new FIFO<LessUgly>();
       private static final POOL_SIZE=5;
       private int count;

       private LessUgly(){
       }

       public static synchronized getInstance(){
         if( session==null){
            session = new Hashtable<String,LessUgly>(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;
       }     
MyStaticClass.GetInstance().DoSomething();
MyStaticClass.DoSomething();
var svc = new MyComplexServce(MyStaticClass.GetInstance());