如何在抽象工厂模式中调用单例类并适配多实现类扩展?
抽象工厂与单例结合的解决方案及模式适配性分析
咱们一步一步来拆解你的问题,先从最核心的单例与工厂结合的实现说起,再聊扩展方案和模式适配性。
一、如何在保留工厂模式的同时返回Treasure的单例实例
你的Treasure类已经实现了线程安全的懒汉式单例,这部分代码是没问题的。要在工厂里返回它的单例,只需要在FactoryClass的OperationInvoke方法中直接返回Treasure.Instance即可——工厂的职责是提供实例,而不是一定要自己创建实例,所以直接复用单例类的已有实例完全符合工厂模式的设计。
修正后的FactoryClass代码如下:
public class FactoryClass : OpClass { public override IHou OperationInvoke(string opClass) { if(opClass == "T") { // 直接返回Treasure的单例实例 return Treasure.Instance; } // 后续新增其他类型的判断逻辑在这里补充 // 如果传入不支持的标识,可以抛出异常或返回null(根据业务需求选择) throw new ArgumentException($"不支持的操作类型: {opClass}"); } }
这样你的Main方法调用逻辑完全不需要修改,就能拿到Treasure的单例并执行Operation方法。
二、新增House、Blocks等类时的最优解决方案
当你需要扩展更多实现IHou接口的类时,可以分两种情况处理,同时优化工厂的扩展性:
1. 若新增类也需要单例
和Treasure一样,给每个类实现线程安全的单例(比如复用Treasure的懒汉式写法),然后在工厂中补充对应的分支判断。如果后续类很多,直接写一堆if-else会违反开闭原则(新增类需要修改工厂代码),推荐用注册式字典优化工厂:
public class FactoryClass : OpClass { // 用字典注册标识与实例获取逻辑的映射 private static readonly Dictionary<string, Func<IHou>> _typeRegistry = new Dictionary<string, Func<IHou>>(); // 静态构造函数中完成注册,新增类只需要加一行注册代码 static FactoryClass() { _typeRegistry.Add("T", () => Treasure.Instance); _typeRegistry.Add("H", () => House.Instance); // 新增House类的注册 _typeRegistry.Add("B", () => Blocks.Instance); // 新增Blocks类的注册 } public override IHou OperationInvoke(string opClass) { if(_typeRegistry.TryGetValue(opClass, out var getInstance)) { return getInstance(); } throw new ArgumentException($"不支持的操作类型: {opClass}"); } }
比如新增的House单例类示例:
public sealed class House : IHou { private static House instance = null; private static readonly object padlock = new object(); private House() { } public static House Instance { get { lock (padlock) { if (instance == null) { instance = new House(); } return instance; } } } public void Operation(Player p, List<Player> lstPlayers) { // 自定义积分逻辑,比如加100分 p.Points += 100; } }
2. 若新增类不需要单例
如果某些类不需要全局唯一实例,工厂可以直接创建新实例返回,字典注册的方式同样适用,只需要把注册的Func<IHou>改成() => new NonSingletonClass()即可,灵活性很高。
三、此场景使用工厂模式是否合适?
非常合适!你的理解完全正确:当多个类共享同一接口(IHou)、拥有共同行为(Operation方法)但具体实现逻辑不同时,工厂模式就是绝佳的选择。
它的优势在于:
- 隐藏实例化细节:调用方(
Main方法)只需要传入标识字符串,不需要关心具体类的创建逻辑(是单例还是新实例) - 降低耦合:调用方依赖的是抽象接口
IHou,而不是具体类,后续替换或新增类时,调用代码完全不需要修改 - 符合开闭原则:通过注册式字典优化后,新增类只需要添加注册代码,不需要修改工厂的核心逻辑
内容的提问来源于stack exchange,提问作者user1400915
相关产品推荐
相关产品推荐

