当实例化时存在对象依赖性时如何实现Singleton?

时间:2011-07-08 11:07:51

标签: c# design-patterns singleton

我有一个单例类,需要实例化对象。

我正在使用这种方法:

  public static AppConfig Instance(IConfigManager configManager)
    {
        if (_instanceHolder == null)
        {
            lock (LockObject)
            {
                if (_instanceHolder == null)
                {
                    _instanceHolder = new AppConfig(configManager);
                }
            }
        }

        return _instanceHolder;
    }

在这种情况下,这是实现单身人士的最佳方式吗?

由于

5 个答案:

答案 0 :(得分:6)

在我看来,在这种情况下使用单身人士似乎是一个非常糟糕的主意。第二个调用将完全忽略 configManager参数,因为它会发现已经有一个实例。这违反了最不出意的原则,IMO。

由于各种原因,单身模式通常讨厌,其中最重要的是可测试性。这个例子更糟糕 - 绝对远离它。

另外,在实现单例模式时,我不会使用双重检查锁定。有关我的首选选项,请参阅my article on the singleton pattern

答案 1 :(得分:2)

似乎IoC容器非常适合这种情况,例如: (使用Ninject)。

IKernel kernel = new StandardKernel();
// register implementor of IConfiguration
kernel.Bind<IConfiguration>().To<Config>();
// register AppConfig as a singleton
kernel.Bind<AppConfig>().ToSelf().InSingletonScope();

...

// get the AppConfig singleton
var appConfig = kernel.Get<AppConfig>();

答案 2 :(得分:0)

双重检查Singleton模式。这里没问题。

答案 3 :(得分:0)

一般来说,当我使用单身时,只能重构一个更大的邪恶,即一个充满静态方法的类。我需要传递一个依赖构造时使用的一个技巧是有两个“实例”方法(或“构造”和“实例”方法):一个接受一个参数而另一个不接受。必须先调用带参数的那个,如果再次调用则抛出一个Error。如果在另一个版本之前调用它,则无参数版本将抛出错误。

这意味着在使用单例时你必须要小心,但至少你应该在运行时快速发现如果你做错了。我希望(在我的情况下和你的情况一样)这只是迈向更好的道路上的一步。

我正在使用Java,但我认为C#中的工作原理基本相同。

答案 4 :(得分:0)

遵循Jon的建议:

 public static void Initialize(IConfigManager configManager)
    {
        if (_instanceHolder == null)
        {
            lock (LockObject)
            {
                if (_instanceHolder == null)
                {
                    _instanceHolder = new AppConfig(configManager);
                    return;
                }
            }
        }

        throw new ApplicationException("Initalize() method should be called only once.");
    }

    /// <summary>
    /// Instances the specified config manager.
    /// </summary>
    /// <returns></returns>
    public static AppConfig Instance
    {
        get
        {
            if (_instanceHolder == null)
            {
                throw new ApplicationException("Singleton instance hasn't been initialized.");
            }

            return _instanceHolder;
        }
    }

我打电话给:

        void Application_Start(object sender, EventArgs e)
    {
        AppConfig.Initialize(new ConfigManagerWrapper());
    }

理想情况下,我应该使用IoC容器。 但我喜欢让AppConfig类具有默认实现,并使其能够用于依赖注入。在这种情况下,我不必在生产中调用Initialize()方法。