如何处理单身人士的集合?

时间:2010-06-21 09:50:47

标签: c# design-patterns singleton c#-4.0

我们有以下类层次结构:

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()函数?

是否可以在这些类的静态构造函数中的静态字典中收集这些类型及其实例(或实例创建委托)? (谢谢Jon,我只记得“.Net 4中的内容有所不同”,但不是details

其他方式将使用BaseManager的类属性或后代或查找IManager的实现。

首选解决方案是什么?

3 个答案:

答案 0 :(得分:3)

静态成员参与的事实使我认为基于字典的方法是最好的,除非你想调用反射并找出检索单例的方法。这是我能够提出的工作示例代码:

// 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 :(得分:1)

我认为最常见的方法是使用类似IServiceProvider的内容。

答案 2 :(得分:0)

最佳方法取决于您期望的用途。如果你只有几个经理,并且你希望偶尔增加这个数字,那么我会采用直截了当的方法:

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

这可以减少错误,确保调用者始终获得他们期望的管理员类型。但是,它确实意味着每次添加一种类型的管理器时都需要更改ManagerFacade,因此在这些情况下它不合适。

如果您需要经常添加新经理,请执行

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

对getManager()背后的逻辑进行硬编码,并使用枚举或等效类型作为类型。这意味着您需要在添加管理器时重写该方法,但界面不会更改。

如果您的经理经常或动态地更换,那么请在适当的经理填充的幕后保留一本字典。使用String作为'type',这样您在添加管理器时就不必更改'enum'类。如果需要,您可以懒惰地初始化经理。

顺便说一句,你确定你需要一个单身人士吗?只是因为你想让ManagerFacade总是返回相同的XManager实例并不意味着XManager需要是一个Singleton。您可以将XManager设置为ManagerFacade的内部,或者通过静态方法限制管理器创建。