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

Jou*_*aas 39 singleton static design-patterns class

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

Jul*_*iet 28

在静态类中优先使用单例的一个很好的理由(假设您没有更好的模式可供使用;)),将一个单例实例与另一个实例进行交换.

例如,如果我有一个这样的日志类:

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

public class Client {
    public void DoSomething() {
        Logger.Log("DoSomething called");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

好的,所以我想热插拔我的Log方法进行测试.去小工具单身!

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Rya*_*yes 10

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

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

资源

编辑:

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

  • Flyweight更像是一个"multiton",而不是真正的单身. (2认同)
  • 它确实存在.见[维基百科](http://en.wikipedia.org/wiki/Multiton_pattern). (2认同)
  • 静态类在许多语言中都是惰性的.它们在被调用之前不会被初始化. (2认同)

小智 7

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

public interface IFooProvider {
  Bar FooBar();
}

public static class Foo {
  public static readonly IFooProvider FooProvider { get; set; }
  public Bar FooBar() { return FooProvider.FooBar(); }
}
Run Code Online (Sandbox Code Playgroud)

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


adi*_*tya 6

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


Mat*_*nen 5

即使恕我直言,单例模式是一种过度使用的模式,它有时也会带来好处,例如:

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