Как обращаться с коллекцией синглетонов? - PullRequest
0 голосов
/ 21 июня 2010

У нас есть следующая иерархия классов:

public interface IManager {
   object GetObject(int);
}

public class BaseManager : IManager ...

public class XManager : BaseManager {
   ...
   public static XManager Instance;
}

public class YManager : BaseManager {
   ...
   public static YManager Instance;
}

public static class ManagerFacade {
   private static IManager GetManager(type);
   public static object GetObject(type, int) { 
     return GetManager(type).GetObject(int); }
}

Как бы вы реализовали функцию GetManager ()?

Можно ли собирать эти типы и их экземпляры (или экземпляры, создающие делегаты) в статическом словаре в статических конструкторах этих классов? (Спасибо, Джон, я только что вспомнил «что-то другое в .Net 4», но не подробности )

Другие способы могли бы использовать атрибуты класса или потомки BaseManager или искать реализации IManager.

Какое решение является предпочтительным?

Ответы [ 3 ]

3 голосов
/ 21 июня 2010

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

// Added another interface - GetInstance
public interface IManager
{
    object GetObject(int i);
}

// made BaseManager abstract; you don't have to do that, but then
// remember to make everything virtual, etc etc.
public abstract class BaseManager : IManager
{
    public abstract object GetObject(int i);
}

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

public class XManager : BaseManager
{
    public static XManager Instance;

    static XManager() { Instance = new XManager(); }

    public override object GetObject(int i)
    {
        return "XManager Instance: index was " + i.ToString();
    }
}

public class YManager : BaseManager
{
    public static YManager Instance;
    static XManager() { Instance = new YManager(); }

    public override object GetObject(int i)
    {
        return "YManager Instance: index was " + i.ToString();
    }
}

ManagerFacade реализует словарь следующим образом:

public static class ManagerFacade
{
    private static readonly Dictionary<Type, IManager> managerInstances 
      = new Dictionary<Type, IManager>()
    {
        {typeof(XManager), XManager.Instance},
        {typeof(YManager), YManager.Instance}
    };

    private static IManager GetManager<T>() where T: IManager
    {
        return managerInstances[typeof(T)];
    }

    public static object GetObject<T>(int i) where T: IManager
    {
        return GetManager<T>().GetObject(i);
    }
}

Консольное приложение для проверки фасада менеджера:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(ManagerFacade.GetObject<XManager>(2).ToString());
        Console.WriteLine(ManagerFacade.GetObject<YManager>(4).ToString());

        // pause program execution to review results...
        Console.WriteLine("Press enter to exit");
        Console.ReadLine();
    }
}

Вывод на консоль:

XManager Instance: index was 2
YManager Instance: index was 4
Press enter to exit

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

1 голос
/ 21 июня 2010

Я думаю, что наиболее распространенный подход - использовать что-то вроде IServiceProvider.

0 голосов
/ 21 июня 2010

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

class ManagerFacade {
  XManager getXManager() {...}
  ....
}

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

Если вам нужно добавлять новые менеджеры довольно часто, то реализуйте

class ManagerFacade {
      IManager getManager(type) {...}
      ....
    }

жесткое программирование логики, стоящей за getManager (), и использование перечисления или эквивалентного типа в качестве типа.Это означает, что вам нужно переписать метод при добавлении менеджера, но интерфейс не меняется.

Если ваши менеджеры меняются часто или динамически, тогда держите словарь за кулисами, которые вы заполняете соответствующими менеджерами,Используйте String как «тип», чтобы вам не приходилось менять класс «enum» при добавлении менеджера.Вы можете лениво инициализировать менеджеров, если вам нужно.

Кстати, вы уверены, что вам нужен синглтон здесь?То, что вы хотите, чтобы ManagerFacade всегда возвращал один и тот же экземпляр XManager, не означает, что XManager должен быть Singleton.Вы можете сделать XManager внутренним для ManagerFacade или ограничить создание менеджера статическим методом.

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