关于IOC工厂模式:是否需重复实例化及优化方案问询
Great question! You're absolutely right that repeatedly instantiating IOCFactory and writing that boilerplate code is redundant and not ideal. Let's look at a few cleaner approaches to solve this:
1. Turn IOCFactory into a Singleton
Since you only need one instance of the factory (it doesn't hold state that changes per use), making it a singleton eliminates the need to new it every time:
class IOCFactory { public enum IOC { TinyIOC } // Singleton instance private static readonly IOCFactory _instance = new IOCFactory(); public static IOCFactory Instance => _instance; // Private constructor to prevent external instantiation private IOCFactory() {} public IIOCService GetService(IOC iocType) { switch (iocType) { case IOC.TinyIOC: return TinyIOCServiceImpl.Current; default: throw new NotSupportedException(); } } }
Now your call simplifies to:
IIOCService iocService = IOCFactory.Instance.GetService(IOCFactory.IOC.TinyIOC);
2. Add Static Shortcut Methods
If you mostly use the default TinyIOC implementation, add a static method to skip both instantiation and enum parameter passing:
class IOCFactory { public enum IOC { TinyIOC } private static readonly IOCFactory _instance = new IOCFactory(); public static IOCFactory Instance => _instance; private IOCFactory() {} public IIOCService GetService(IOC iocType) { switch (iocType) { case IOC.TinyIOC: return TinyIOCServiceImpl.Current; default: throw new NotSupportedException(); } } // Static shortcut for default container public static IIOCService GetDefaultService() { return Instance.GetService(IOC.TinyIOC); } }
Call it with one line:
IIOCService iocService = IOCFactory.GetDefaultService();
3. Global Static Entry Point (Even Cleaner)
Since your TinyIOCServiceImpl is already a singleton, you can wrap it in a static utility class to skip the factory entirely (great if you don't plan to switch containers often):
public static class IOCContainer { // Direct access to your default IOC service public static IIOCService Default => TinyIOCServiceImpl.Current; // Optional: Keep factory support if you need to switch later public static IIOCService GetService(IOCFactory.IOC iocType) { return IOCFactory.Instance.GetService(iocType); } }
Now usage is as simple as:
IIOCService iocService = IOCContainer.Default;
4. Constructor Injection (Most Elegant, Best Practice)
To fully decouple your classes from static calls, use constructor injection. Initialize your IIOCService once at app startup, then inject it into any class that needs it:
// Example business class that depends on IIOCService public class OrderProcessor { private readonly IIOCService _iocService; // Inject IIOCService via constructor public OrderProcessor(IIOCService iocService) { _iocService = iocService; } public void ProcessOrder() { // Use the injected service _iocService.RegisterSingleton<IOrderRepository>(); var repo = _iocService.Resolve<IOrderRepository>(); // ... } } // App startup logic public static void Main() { // Initialize your IOC service once IIOCService iocService = IOCFactory.GetDefaultService(); // Register your business classes with the container iocService.RegisterSingleton<OrderProcessor>(); // Retrieve instances - dependencies are injected automatically var processor = iocService.Resolve<OrderProcessor>(); processor.ProcessOrder(); }
This approach follows dependency injection principles, makes your code easier to test (you can mock IIOCService), and eliminates boilerplate entirely in your business logic.
Summary
- Use singleton factory or static shortcuts for quick, low-effort reduction of redundancy.
- Use global static entry if your container implementation is stable.
- Use constructor injection for the most maintainable, testable, and decoupled solution.
内容的提问来源于stack exchange,提问作者Fabrizio Stellato

