简体   繁体   English

是否可以创建一个Singleton工厂类来维护实例的字典?

[英]Is it possible to create a Singleton factory class maintaining a dictionary for instances?

I have multiple classes that inherit from IPrint. 我有多个继承自IPrint的类。 I want to instantiate these classes using a factory but I want to maintain a single instance of each type. 我想使用工厂实例化这些类,但是我想维护每种类型的单个实例。 Is this possible? 这可能吗?

Please find my sample code below. 请在下面找到我的示例代码。

 public interface IPrint
    {
        void DoPrint();
    }
    public class DigitalPrint : IPrint
    {
        public void DoPrint()
        {
            // logic
        }
    }
    public class InkPrint : IPrint
    {
        public void DoPrint()
        {
            // logic
        }
    }
    public class PrintFactory
    {
        private static IDictionary<IPrint, object> prints = new 
   Dictionary<IPrint, object>();
        private PrintFactory()
        {

        }
        public static IPrint GetPrint(PrintType type)
        {
            // return instance depending on type. Instantiate only once 
             //like singleton
            // How to write so that it returns a single instance depending 
            //on type
            return null;
        }
    }

    public enum PrintType
    {
        DigitalPrint,
        InkPrint
    }

Can someone give me some idea if this is possible? 有人可以给我一些想法吗?

Thanks. 谢谢。

You can create IPrint instances when initializing Dictionary<PrintType, IPrint> : 您可以在初始化Dictionary<PrintType, IPrint>时创建IPrint实例:

private static IDictionary<PrintType, IPrint> prints = 
  new Dictionary<PrintType, IPrint> {
      { PrintType.DigitalPrint, new DigitalPrint() },
      { PrintType.InkPrint, new InkPrint() }
  };

Getting print (thus print is a class, the same instance will be returned for each request): 获取打印(因此打印是一个类,每个请求将返回相同的实例):

public static IPrint GetPrint(PrintType type)
{
    IPrint print;
    if (!prints.TryGetValue(type, out print))
       return null;

    return print;
}

If you don't want to create IPrint instances until the client asks for them, you can use Dictionary<PrintType, Lazy<IPrint>> : 如果您不希望在客户端请求之前创建IPrint实例,则可以使用Dictionary<PrintType, Lazy<IPrint>>

private static IDictionary<string, Lazy<IPrint>> prints =
    new Dictionary<string, Lazy<IPrint>> {
        { PrintType.DigitalPrint, new Lazy<IPrint>(() => new DigitalPrint()) },
        { PrintType.InkPrint, new Lazy<IPrint>(() => new InkPrint()) }
    };

Getting print (in this case only one instance of each IPrint type will be created, but not before someone tries to get the instance of that type): 获取打印(在这种情况下,只会创建每种IPrint类型的一个实例,但不会在有人尝试获取该类型的实例之前创建):

public static IPrint GetPrint(PrintType type)
{
    Lazy<IPrint> factory;
    if (!prints.TryGetValue(type, out factory))
       return null;

    return factory.Value;
}

Though I would consider using dependency injection framework instead of implementing such functionality manually. 尽管我会考虑使用依赖项注入框架,而不是手动实现此类功能。

Further reading: Ninject or Autofac 进一步阅读: NinjectAutofac

Yes, it's possible. 是的,有可能。

This creates the IPrint 's before they're needed. 这将在需要之前创建IPrint You could make them lazily created, instead. 您可以改为懒惰地创建它们。

public class Program
{
    public static void Main(string[] args)
    {
        var factory = new PrintFactory();
        Console.WriteLine(PrintFactory.GetPrint(PrintType.DigitalPrint));
        Console.WriteLine(PrintFactory.GetPrint(PrintType.InkPrint));
    }
}

public interface IPrint
{
    void DoPrint();
}

public class DigitalPrint : IPrint
{
    public void DoPrint()
    {
        // logic
    }
}

public class InkPrint : IPrint
{
    public void DoPrint()
    {
        // logic
    }
}

public class PrintFactory
{
    // Make the dictionary from PrintType to IPrint instead of IPrint to object
    private static IDictionary<PrintType, IPrint> prints = new Dictionary<PrintType, IPrint>();

    // Initialize prints in a static constructor.
    static PrintFactory()
    {
        prints.Add(PrintType.DigitalPrint, new DigitalPrint());
        prints.Add(PrintType.InkPrint, new InkPrint());
    }

    public static IPrint GetPrint(PrintType type)
    {
        if (!prints.ContainsKey(type)) 
        {
            // TODO: Maybe throw an exception or log?
        }
        return prints[type];
    }
}

public enum PrintType
{
    DigitalPrint,
    InkPrint
}

I would get rid of the enum and make a generic method: 我将摆脱枚举并制作一个通用方法:

public static IPrint GetPrint<T>() where T : IPrint, new ()
{
    foreach (var key in prints.Keys) {
        if (key is T)
            return null;
    }
           return new T();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM