我创造的这个单身人士怎么了?

时间:2010-09-01 14:35:37

标签: c# design-patterns singleton

我创建了一个类,它允许访问对变量的全局访问,同时只创建一次,基本上是单例。

但是,它与实现单例的任何“正确”方法都不匹配。我假设它没有被提及,因为它有一些'错误',但除了懒惰的初始化之外,我看不出任何问题。

有什么想法吗?

static class DefaultFields
{
    private static readonly string IniPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "defaultFields.ini");
    private static readonly IniConfigSource Ini = GetIni();               

    /// <summary>
    /// Creates a reference to the ini file on startup
    /// </summary>
    private static IniConfigSource GetIni()
    {
        // Create Ini File if it does not exist
        if (!File.Exists(IniPath))
        {
            using (FileStream stream = new FileStream(IniPath, FileMode.CreateNew))
            {
                var iniConfig = new IniConfigSource(stream);
                iniConfig.AddConfig("default");
                iniConfig.Save(IniPath);
            }
        }

        var source = new IniConfigSource(IniPath);
        return source;
    }

    public static IConfig Get()
    {
        return Ini.Configs["default"];
    }

    public static void Remove(string key)
    {
        Get().Remove(key);
        Ini.Save();
    }

    public static void Set(string key, string value)
    {
        Get().Set(key, value ?? "");
        Ini.Save();
    }
}

8 个答案:

答案 0 :(得分:5)

它不遵循通常的单例模式,因为您的类是静态的,只是控制对静态变量的访问。

作为单例通常是类的静态单个实例,其中唯一的静态函数是创建和访问将变量存储为普通非静态成员变量的单例。

意味着这个类可以很容易地被改变或者被设置为多一次但是你的不能

答案 1 :(得分:4)

你对单身人士是正确的,它是一个具有提供全局访问的唯一实例的类。

它可能看起来像一个静态类,但通常以不同的方式实现。

另外请记住,这种模式应该用于一些预防措施,因为它很难在代码深处重构一个单例。主要用于硬件限制或实现工厂的唯一访问点时。我尽量避免使用它。

实施的一个例子如下:

public class A
{
    /// <summary>
    /// Unique instance to access to object A
    /// </summary>
    public static readonly A Singleton = new A();

    /// <summary>
    /// private constructor so it can only be created internally.
    /// </summary>
    private A()
    {
    }

    /// <summary>
    /// Instance method B does B..
    /// </summary>
    public void B()
    {
    }
}

可以像

一样使用
  

A.Singleton.B()

希望有所帮助。

答案 2 :(得分:2)

您班级上的所有方法都是静态的,因此您将隐藏用户的单个实例。使用singleton pattern,单个实例通过通常称为Instance的公共属性公开(在其他语言中,如Java,它可能是一个名为getInstance或类似的方法)。

alt text

你的代码没错 - 它不是单身模式。如果你想实现单身人士,我会推荐Jon Skeet的文章Implementing the Singleton Pattern in C#

答案 3 :(得分:2)

我看到的最大问题是你没有对你的INI文件进行任何SyncLock处理 - 试图同时写入值的多个线程最终会产生不可预测的结果,比如两者进行写入并且只有一个持久化(或多个线程尝试一次写入文件,导致IO错误)。

我创建一个私有的“Locking”对象,然后将写入包装到SyncLock的文件中,以确保一次只有一个线程能够更改值(或者,至少,提交对INI文件的更改)。

答案 4 :(得分:0)

这不是一个单身,它是一个静态类。

在很多方面,静态类与单例类似,都是真的。但是静态类不能实现接口,不能从基类继承功能,也不能对它们进行引用。

答案 5 :(得分:0)

为什么只读取Ini字段?

但是如果你想实现单例模式,它就是这样的:

static DefaultFields
{
    private readonly string IniPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "defaultFields.ini");
    private readonly IniConfigSource Ini = GetIni();               

    private static DefaultFields _default;

    public static DefaultFields Default 
    { 
        get { if(this._default == null){ this._default = new DefaultFields(); } return this._default; } 
    }

    private DefaultFields()
    {

    }

    /// <summary>
    /// Creates a reference to the ini file on startup
    /// </summary>
    private IniConfigSource GetIni()
    {
        // Create Ini File if it does not exist
        if (!File.Exists(IniPath))
        {
            using (FileStream stream = new FileStream(IniPath, FileMode.CreateNew))
            {
                var iniConfig = new IniConfigSource(stream);
                iniConfig.AddConfig("default");
                iniConfig.Save(IniPath);
            }
        }

        var source = new IniConfigSource(IniPath);
        return source;
    }

    public IConfig Get()
    {
        return Ini.Configs["default"];
    }

    public void Remove(string key)
    {
        Get().Remove(key);
        Ini.Save();
    }

    public void Set(string key, string value)
    {
        Get().Set(key, value ?? "");
        Ini.Save();
    }
}

答案 6 :(得分:0)

我也对这个问题的答案感兴趣。在我看来,有大量的单例示例使用惰性实例化,但我认为你必须根据具体情况问自己是否真的有必要。

尽管本文与Java有关,但这些概念仍应适用。这为不同的单例实现提供了许多示例。 http://www.shaunabram.com/singleton-implementations/

我也看过许多对“Effective Java”一书的引用,第71项 - 明智地使用惰性实例化。基本上,除非你需要,否则不要这样做。

答案 7 :(得分:0)

延迟初始化对于单例类非常重要。通过声明您的类是静态的,您实现了一个静态类,而不是单例类。