You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在抽象工厂模式中调用单例类并适配多实现类扩展?

抽象工厂与单例结合的解决方案及模式适配性分析

咱们一步一步来拆解你的问题,先从最核心的单例与工厂结合的实现说起,再聊扩展方案和模式适配性。

一、如何在保留工厂模式的同时返回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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:04:52