【问题标题】:Singleton class for an object with parameters带有参数的对象的单例类
【发布时间】:2014-10-22 17:11:40
【问题描述】:

我意识到我应该一次只运行一个名为StdSchedulerFactory 的对象的实例。到目前为止,我实例化了这样的对象

StdSchedulerFactory sf = new StdSchedulerFactory(properties);

属性NameValueCollection。 如何为这个对象编写一个 Singleton 类,以便变量 sf 在整个程序中始终有一个实例?

【问题讨论】:

  • 如果有人实例化了第二个会发生什么?你宁愿不进行适当的单元测试会不会很糟糕?
  • @nvoigt 完全可以对单例进行单元测试,它只需要派生一个接口;然后你可以模拟它来测试其他对象,当你测试 it 时,它是一个单例并不重要。 (请注意,您需要一个 DI 容器才能工作)。
  • @BradleyDotNET 如果您的测试相互影响,您将如何对单例进行单元测试?你会构建一个单一的、整体的测试用例来调用类可以拥有的所有操作吗? (不是说 DI 容器中普通类的单例生命周期,而是真正的私有构造函数单例)
  • @nvoigt 如果存在这种类,我可能不会将其设为单例。如果它确实需要是一个单例,那么是的,“单片”测试最有意义。不理想,但我认为单身人士有时会受到不好的评价。我的代码中有单例,我的单元测试非常合理。

标签: c# design-patterns singleton


【解决方案1】:

Singleton 模式的一部分通常是私有构造函数,因此其他类无法创建新实例。

对于来自类外的参数的解决方法是添加“Init”或“Configure”函数:

public static void Configure(NameValueCollection properties)
{
}

当然,如果你忘记调用这个函数,你可能会得到你不想要的行为;所以你可能想设置一个“已配置”标志或类似的东西,这样如果这个函数还没有被调用,你的其他函数就可以做出适当的反应。

【讨论】:

  • 对不起,我不太明白这一点。您能告诉我在我的情况下必须如何使用您的配置功能吗?
  • @Pedram 它只是单例类中的一个公共方法。您在程序启动附近的某个时间调用它(最好在调用任何依赖于参数的方法之前)。
  • @BradleyDotNET 有时这是单身人士需要的东西,即这解决了我需要做的事情(+1),但我不想“违背常规”?这是一种不常见的做法吗?
  • @Thomas 惯用的 Singleton 不需要它。您可以通过公开其他人设置的属性来做同样的事情。这只是最接近参数化构造函数的类比。至于这种不常见的做法,不,我认为这是很常见的。
【解决方案2】:

这是一个基本的单例实现。它不是线程安全的。

public sealed class StdSchedulerFactory
{
   private static readonly StdSchedulerFactory instance;
   private NameValueCollection _properties;

   private StdSchedulerFactory(NameValueCollection properties)
   {
       _properties = properties;
   }

   public static StdSchedulerFactory GetInstance(NameValueCollection properties)
   {
      if (instance == null)
      {
         instance = new StdSchedulerFactory(properties);
      }
      else
      {
         return instance;
      }
   }
}

【讨论】:

  • 值得注意的是,在顶部添加一个只读对象是一种使其线程安全的简单方法(以及围绕属性/方法的适当锁定)。
  • 您可能打算传递属性。我讨厌这种模式……这意味着我传递了一组属性,但我得到了一个使用完全不同组属性创建的实例。我讨厌欺骗我的方法。
  • 是的,错过了。我同意,有更好的方法。
  • @CamBruce 我收到两个错误:当我尝试像问题中那样实例化它时,StdSchedulerFactory 不包含采用 1 个参数的构造函数。第二个“不能分配静态只读字段(静态构造函数或变量初始化程序除外)。”
【解决方案3】:

这是我最喜欢的两种实现简单单例模式的方式。第二个在调试时更容易:)

public sealed class SingletonOne
{
    private static readonly Lazy<SingletonOne> instance = new Lazy<SingletonOne>(() => new SingletonOne());

    private Lazy<Controller> controller = new Lazy<Controller>(() => new Controller(properties));

    private static object properties = null;

    public static SingletonOne Instance { get { return instance.Value; } }

    public Controller GetController(object properties)
    {
        SingletonOne.properties = properties;

        return this.controller.Value;
    }
}

public sealed class SingletonTwo
{
    private static readonly SingletonTwo instance = new SingletonTwo();

    private Controller controller;

    private static object properties = null;

    public static SingletonTwo Instance
    { 
        get 
        { 
            return SingletonTwo.instance; 
        } 
    }

    public Controller GetController(object properties)
    {
        SingletonTwo.properties = properties;

        if(this.controller == null)
        {
            this.controller = new Controller(SingletonTwo.properties);
        }

        return this.controller;
    }
}

public class Controller 
{
    public Controller(object properties) { }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    相关资源
    最近更新 更多