为什么使用单例而不是静态类?

时间:2010-06-03 20:40:53

标签: design-patterns class static singleton

单身实际上什么时候比静态类更容易或更好?在我看来,创建单身只是额外的努力,实际上并不需要,但我确信有一个很好的理由。否则,显然不会使用它们。

7 个答案:

答案 0 :(得分:27)

在静态类中优先考虑单例的一个很好的理由(假设你没有更好的模式;)),将一个单例实例与另一个实例交换。

例如,如果我有这样的日志记录类:

public static class Logger {
    public static void Log(string s) { ... }
}

public class Client {
    public void DoSomething() {
        Logger.Log("DoSomething called");
    }
}

它工作得很好,但是如果Logger将数据写入数据库或将输出写入控制台会怎样。如果你正在编写测试,你可能不希望所有这些副作用 - 但由于log方法是静态的,除了以外你不能做任何事情。

好的,所以我想热插拔我的Log方法进行测试。 Go go gadget singleton!

public class Logger {
    private static Logger _instance;
    public static Logger Instance
    {
        get
        {
            if (_instance == null)
                _instance = new Logger();
            return _instance;
        }
        set { _instance = value; }
    }
    protected Logger() { }
    public virtual void Log(string s) { ... }
}

public class Client {
    public void DoSomething() {
        Logger.Instance.Log("DoSomething called");
    }
}

因此,您可以使用空TestLogger : Logger方法定义Log,然后将测试记录器的实例设置为单例实例以进行测试。普雷斯托!您可以在不影响客户端代码的情况下热切换您的记录器实现以进行测试或生产。

答案 1 :(得分:10)

单身人士往往更喜欢全球变量,因为:

  • 它们不会使用不必要的变量污染全局命名空间(或者,在具有命名空间的语言中,包含其命名空间)。
  • 它们允许延迟分配和初始化,而许多语言中的全局变量将始终消耗资源。

Source

修改

单身人士的一个很酷的用途是,当与工厂方法结合使用时,可以用来创建Flyweight pattern。这是当你创建一个新对象时,Factory(而不是创建一个新对象)首先检查是否已经创建了该对象的单例,如果是,它只返回该对象,如果没有,它会创建一个新的单例并返回,跟踪它创建的单身人士。 Flyweights的工作原因是单身人士的不变性。

答案 2 :(得分:7)

单身人士对我来说似乎总是多余。我更喜欢静态类,如果我需要不同的行为,我将它与依赖注入和提供者结合起来......我不知道它是什么模式,或者它是否有名称,但它通常是这样的:< / p>
public interface IFooProvider {
  Bar FooBar();
}

public static class Foo {
  public static readonly IFooProvider FooProvider { get; set; }
  public Bar FooBar() { return FooProvider.FooBar(); }
}

然后我确保在我的init方法中将提供程序设置在某处。如果您想通过在类初始化时设置默认提供程序,则可以轻松添加延迟初始化。最重要的是,它允许您在保持使用静态类的美感的同时改变行为。

答案 3 :(得分:4)

尽管恕我直言,单身人士模式是一种过度使用的模式,但它确实有时会带来好处,例如:

  • 使用不同类型的对象(从同一个基础继承)的能力(例如,考虑使用文件系统的数据提供者和一个SQL数据库)
  • 串行性。我没有使用可以自动序列化静态类的框架。
  • 使用较少的静态字段。对于某些人来说,这更具有审美特征,但在某些情况下它具有实际的好处。

答案 4 :(得分:3)

在许多语言中,静态类缺少有用的功能,如继承(以及更普遍的多态)。

Not that I'm advocating singletons。)

答案 5 :(得分:2)

Singletons保留了传统的类方法,并且不要求您在任何地方使用static关键字。它们最初可能要求更高,但会大大简化程序的体系结构。与静态类不同,我们可以使用单例作为参数或对象。

此外,您可以像其他任何类一样使用带有接口的单例。

答案 6 :(得分:2)

  1. Singleton可以实现接口,继承自其他类
  2. 当加载包含类的程序或命名空间时,可以懒惰地或异步地初始化Singleton并由.NET Framework CLR(公共语言运行库)自动加载。虽然静态类通常在首次加载时初始化,但它会导致潜在的类加载器问题。
  3. Singleton类遵循面向对象原则
  4. Singleton Objects存储在堆上,而静态类存储在堆栈中。
  5. Singleton Objects可以有构造函数,而Static Class则不能。
  6. Singleton Objects可以处置但不能处理静态类
  7. Singleton Objects可以克隆但不能使用静态类