От новичка до гуру: Курсы программирования на CyberDuff

Статический доступ к многоэкземплярной переменной

У меня есть одноэлементный экземпляр, на который ссылаются во всем проекте, который работает как шарм. Это избавляет меня от необходимости передавать экземпляр объекта каждому маленькому классу в проекте. Однако теперь мне нужно управлять несколькими экземплярами предыдущей настройки, а это означает, что шаблон синглтона ломается, поскольку каждому экземпляру потребуется собственный экземпляр синглтона.

Какие есть варианты для сохранения статического доступа к синглтону? Чтобы быть более конкретным, у нас есть наш игровой движок, и несколько компонентов и плагинов ссылаются на движок через статическое свойство. Теперь на нашем сервере необходимо разместить несколько экземпляров игры, каждый из которых имеет собственный движок, а это означает, что на стороне сервера шаблон singleton нарушается.

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

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

15.04.2010

  • Пока вы используете синглтоны и статический доступ, вы застряли при тестировании своих классов с производственной версией синглтона (жесткая связь). Рассмотрите возможность перехода к внедрению конструктора и, при желании, к инфраструктуре контейнеров DI (Dependency Injection). 16.04.2010
  • Внедрение конструктора - это то, чего я пытаюсь избежать. У нас более 50 классов, которые ссылаются на движок, и необходимость изменения всех их конструкторов для работы с движком потребует огромного количества работы, и это как бы кажется излишним, когда статическая переменная настолько близка к тому, что нам нужно. Внедрение зависимостей может быть ответом. Я займусь этим. Хотя, похоже, много работы. 16.04.2010
  • Измените свой синглтон, чтобы искать значения в хеш-таблице, используя уникальный идентификатор в качестве ключа. 16.04.2010
  • Westgate, ключ должен быть известен всем объектам, которые хотят ссылаться на одноэлементный объект, таким образом снова заставляя все объекты принимать один и тот же объект (в данном случае ключ) в качестве параметра в какой-то момент. 16.04.2010
  • если издержки рефакторинга являются основной проблемой при изменении всех конструкторов, вы можете попробовать инструмент рефакторинга, такой как Resharper. Для каждого класса вы просто нажимаете вызов Singleton.Instance, затем Refactor | Введите поле и замените все вхождения. Он представит новое частное поле, которое задается в конструкторе. Теперь вам просто нужно изменить изолированный вызов Singleton.Instance на параметры, передаваемые через конструктор, то есть просто Refactor | Введите параметр. Теперь все вызовы конструктора будут иметь фиктивный элемент, который компилятор укажет при сборке. 16.04.2010

Ответы:


1

Самое близкое, что вы могли бы сделать, - это использовать атрибут ThreadStatic в вашей переменной экземпляра singleton. Это сохранит статическую семантику с точки зрения доступа, но каждый поток будет иметь свой собственный экземпляр.

public class ThreadStaticSingleton
{
    [ThreadStatic]
    private static ThreadStaticSingleton instance;

    public static ThreadStaticSingleTon Instance
    {
        get 
        {
            if(instance == null) instance = new ThreadStaticSingleton();

            return instance;
        }
    }
}

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

Другими словами, это сработает, если выполнены оба из следующих условий:

  • Каждый игровой движок работает в собственном потоке
  • Каждый игровой движок только работает в одном потоке.

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

15.04.2010
  • Действительно классная функция, но не совсем подходящее решение этой проблемы. Несколько двигателей будут работать в одном потоке. Наличие ключа вызывает ту же проблему - всем классам, использующим движок, потребуется статический доступ к ключу, а затем мы вернемся к основному. 16.04.2010
  • @Qua: Это уже не синглтон по определению. Похоже, что требуется переменная экземпляра вашего ранее одноэлементного типа на вашем игровом движке. Я не думаю, что можно будет решить эту проблему без некоторого рефакторинга. 16.04.2010
  • Мы изменили структуру, чтобы каждый экземпляр игры работал в отдельных потоках. В любом случае, мы должны правильно поступить с самого начала. Потрясающий атрибут. 28.04.2010

  • 2

    В этом случае паттерн Синглтон ломается. Было удобно иметь единое место, где весь ваш код мог бы получить экземпляр, но теперь вам нужно хранить несколько экземпляров. Однако вы правы в том, что передавать экземпляры контекста через цепочки конструкторов вашего дерева объектов очень раздражает. Одним из решений этой проблемы является использование инфраструктуры инверсии управления, например Ninject. Это немного связано с инвестициями в дизайн (поскольку требуется некоторое время, чтобы привыкнуть к использованию IoC), но он особенно хорош для решения этих проблем, когда вы хотите использовать внедрение зависимостей (передавая свой GameEngine различным классам), но не делайте этого. Я не хочу писать кучу связующего кода, чтобы просто передавать ссылки.

    Тем не менее, если у вас есть только один такой контекст (т.е. только GameEngine является вашим синглтоном), то, вероятно, проще всего просто добавить его ко всем вашим конструкторам.

    15.04.2010

    3

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

    Есть и другие способы сделать это без использования синглтона, но что-то вроде этого может сработать для вас (примечание: я не компилировал и не тестировал это, но это может дать вам начало).

    public class MySingleton
    {
        private static Dictionary<string, MySingleton> myInstances = new Dictionary<string, MySingleton>();
    
        private MySingleton()
        {
            // construct instance
        }
    
        // note: could also implement using an indexer
        // also note: this is not thread-safe, but you could add a lock around it
        public static MySingleton GetInstance(string key)
        {
            if (!myInstances.ContainsKey(key))
            {
                myInstances.Add(key, new MySingleton());
            }
            return myInstances[key];
        }
    
        // other methods
    }
    
    15.04.2010
  • И как мои классы узнают, какой ключ использовать? Я не понимаю, как это вообще что-то исправить. Раньше мне был нужен статический доступ к моему синглтону - теперь мне нужен статический доступ к какому-то произвольному ключу. 16.04.2010
  • Если каждому из ваших игровых экземпляров требуется доступ к другому экземпляру, вам придется как-то идентифицировать каждый из ваших экземпляров. Как вы определяете каждый из своих уникальных игровых экземпляров? У вас есть GameID или GameName или что-то в этом роде? 16.04.2010
  • Скажем, я создаю экземпляр игрового движка с ключом kek. Теперь все экземпляры классов, ссылающиеся на этот конкретный игровой движок, должны будут знать ключ, чтобы ссылаться на экземпляр игры. Как все эти экземпляры узнают ключ, если я не передам его им каким-либо образом? Каждая игра / движок имеет уникальный идентификатор. 16.04.2010
  • Если вы не хотите, чтобы ваши другие игровые объекты отслеживали ключ, вы можете начать смотреть на структуру внедрения зависимостей, чтобы автоматически внедрять экземпляры вещей в ваши классы. См. Ответ Дэна Брайанта. Масштабирование дизайна с одним экземпляром до поддержки нескольких экземпляров не является тривиальным делом, вам нужно что-то сделать, чтобы различать уникальные экземпляры игры. 16.04.2010
  • Новые материалы

    Представляем Narwhal Technologies (Nrwl)
    6 декабря 2016 г. Маунтин-Вью, Калифорния С тех пор, как Виктор Савкин и я (Джефф Кросс) присоединились к команде Angular в Google на заре Angular 1, Angular продемонстрировал феноменальный..

    Путь AWS  — «Изучение машинного обучения — 10 начинающих ИИ и машинного обучения на AWS».
    Универсальный ресурсный центр для изучения искусственного интеллекта и машинного обучения. НОЛЬ или ГЕРОЙ, начните свое путешествие здесь. Получите решения и пройдите обучение у экспертов AWS...

    5 простых концепций Python, ставших сложными
    #заранее извините 1) Переменные x = 4 y = 5 Переменная в Python — это символическое представление объекта. После присвоения некоторого объекта переменной Python мы приобретаем..

    «Освоение вероятности: изучение совместной, предельной, условной вероятности и теоремы Байеса —…
    Виды вероятности: Совместная вероятность Предельная вероятность Условная вероятность Диаграмма Венна в вероятностях: В “Set Theory” мы создаем диаграмму Венна...

    Основы Spring: Bean-компоненты, контейнер и внедрение зависимостей
    Как лего может помочь нашему пониманию Когда мы начинаем использовать Spring, нам бросают много терминов, и может быть трудно понять, что они все означают. Итак, мы разберем основы и будем..

    Отслеживание состояния с течением времени с дифференцированием снимков
    Время от времени что-то происходит и революционизирует часть моего рабочего процесса разработки. Что-то более забавное вместо типичного утомительного и утомительного процесса разработки. В..

    Я предполагаю, что вы имеете в виду методы обработки категориальных данных.
    Я предполагаю, что вы имеете в виду методы обработки категориальных данных. Пожалуйста, проверьте мой пост Инструментарий специалиста по данным для кодирования категориальных переменных в..