Что не так с этим синглтоном, который я создал - PullRequest
4 голосов
/ 01 сентября 2010

Я создал класс, который предоставляет доступ к глобальному доступу к переменной, создавая ее только один раз, по сути, в виде одиночного файла.

Однако он не соответствует ни одному из «правильных» способов реализации синглтона. Я предполагаю, что это не упомянуто, потому что есть что-то «не так» с этим, но я не вижу никаких проблем с этим кроме отсутствия ленивой инициализации

Есть мысли?

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 ]

5 голосов
/ 01 сентября 2010

Он не следует обычным одноэлементным шаблонам, поскольку ваш класс статичен и просто контролирует доступ к статическим переменным.

Где в качестве синглтона обычно используется один статический экземпляр класса, где единственными статическими функциями являются создание и доступ к синглтону, который хранит переменные как обычные нестатические переменные-члены.

Это означает, что класс можно легко изменить или сделать экземпляром более одного раза, но ваш не может

4 голосов
/ 01 сентября 2010

Вы правы насчет синглтона, его класса с уникальным экземпляром, который обеспечивает глобальный доступ.

Может показаться, что статический класс, но обычно он реализован по-другому.

Также имейте в виду, что этот шаблон следует использовать с некоторой осторожностью, так как его действительно трудно реорганизовать синглтоном, когда он глубоко в коде. Следует использовать в первую очередь, когда у вас есть аппаратные ограничения или реализованы уникальные точки доступа к фабрике. Я постараюсь избежать этого, когда это возможно.

Примером реализации является следующий:

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 голосов
/ 01 сентября 2010

Самая большая проблема, которую я вижу, заключается в том, что вы не выполняете никаких операций SyncLock при записи в ваш INI-файл - несколько потоков, пытающихся записать значения одновременно, могут привести к непредсказуемым результатам, как и при выполнении записи.и только один постоянный (или несколько потоков, пытающихся записать файл одновременно, что приводит к ошибке ввода-вывода).

Я бы создал какой-то частный объект «Блокировка», а затем обернул бы записи в ваш файлв SyncLock, чтобы гарантировать, что только один поток одновременно может изменять значения (или, по крайней мере, фиксировать изменения в файле INI).

2 голосов
/ 01 сентября 2010

Все методы в вашем классе являются статическими, поэтому вы скрываете один экземпляр от своих пользователей. С одноэлементным шаблоном единственный экземпляр предоставляется через открытое свойство, обычно называемое Instance (в других языках, таких как Java, это может быть метод с именем getInstance или аналогичный).

alt text

Ваш код не ошибается - это просто не шаблон синглтона. Если вы хотите реализовать синглтон, я бы порекомендовал статью Джона Скита Реализация шаблона синглтона в C # .

0 голосов
/ 01 сентября 2010

Ленивая инициализация очень важна для одноэлементного класса.Объявляя ваш класс статическим, вы реализуете статический класс, а не класс синглтона.

0 голосов
/ 01 сентября 2010

Меня также интересуют ответы на этот вопрос.На мой взгляд, существует множество одиночных примеров, в которых используется ленивая реализация, но я думаю, что вы должны спросить себя, действительно ли это необходимо в каждом конкретном случае.

Хотя эта статья относится к Java, концепциидолжно все еще применяться.Это предоставляет ряд примеров для различных одноэлементных реализаций.http://www.shaunabram.com/singleton-implementations/

Я также видел многочисленные ссылки на книгу «Эффективная Java», пункт 71 - используйте ленивый экземпляр разумно.По сути, не делайте этого, если вам не нужно.

0 голосов
/ 01 сентября 2010

Почему только для чтения на поле Ини?

Но если вы хотите реализовать шаблон синглтона, это будет примерно так:

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();
    }
}
0 голосов
/ 01 сентября 2010

Это на самом деле не синглтон, это статический класс.

Во многих отношениях статические классы похожи на синглтон, правда.Но статические классы не могут реализовывать интерфейсы, не могут наследовать функциональность от базового класса, и вы не можете иметь ссылку на них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...