Если не синглтон, то что? - PullRequest
2 голосов
/ 06 октября 2009

Итак, я работаю на уровне промежуточного программного обеспечения.

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

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

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

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

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

Для этого я бы с ума сошел что-то сделатьвот так, чтобы в принципе дать моему синглтону конструктор:

public class MySingleton
{
 private static MySingleton _MySingleton;
 private static object singletonLock = new object();

 private MySingleton(int foo1, string foo2)
 {
  //do init stuff
 }

 public static MySingleton StartSingleton(int foo1, string foo2)
 {
  try
  {
   Monitor.Enter(singletonLock);
   if (_MySingleton == null)
   {
    _MySingleton = new MySingleton(foo1, foo2);
   }
   else
    throw new Exception("Singleton already initialized");
  }
  finally
  {
   Monitor.Exit(singletonLock);
  }
  return _MySingleton;
 }

 public static MySingleton Instance
 {
  get
  {
   try
   {
    Monitor.Enter(singletonLock);
    if (_MySingleton == null)
    {
     throw new Exception("Singleton must be Initialized");
    }
   }
   finally
   {
    Monitor.Exit(singletonLock);
   }
   return _MySingleton;
  }
 }
}

Ответы [ 3 ]

4 голосов
/ 06 октября 2009

Это не сумасшедший код, но в любом случае это синглтон. Если вы удалите свойство Instance, оно больше не будет одноэлементным.

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

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

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

1 голос
/ 06 октября 2009

Ты не будешь сумасшедшим. Синглтон позволяет избежать недостатков глобальных переменных благодаря пространству имен. Несмотря на то, что он доступен глобально через статический вызов функции, он не является глобальной переменной. Более того, доступ к нему осуществляется через пространство имен, поэтому никто, вероятно, не поместит его в глобальную переменную с именем temp, а затем назначит что-то еще для temp. Они всегда должны получить локальную ссылку на него, выполнив

MySingleton singletonRef = MySingleton.Instance ();

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

0 голосов
/ 06 октября 2009

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

public class MySingleton
{
    private static int objectCount = 0;
    private static object singletonLock = new object();

    public MySingleton(int foo1, string foo2)
    {
        try{
            Monitor.Enter(singletonLock);
            if (objectCount != 0)
            {
                throw new Exception("MySingleton Already exsists");
            }
            else
            {
                objectCount++;
            }
        }
        finally{
            Monitor.Exit(singletonLock);
        }

        //do initialization stuff

    }
}

явно больше не настоящий синглтон.

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