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

如何基于参数类型简化对象内的类初始化流程

优化基于类型参数的类初始化方案(替代冗余switch)

方案一:字典映射的工厂类(推荐)

这种方式用字典存储类型到实例创建逻辑的映射,既保留了switch的性能,又解决了冗余和扩展性问题,符合开闭原则(新增类型无需修改原有逻辑)。

实现步骤:

  1. 定义静态工厂类,维护类型与创建函数的映射字典:
public static class QuestObjectiveFactory
{
    // 字典键为ObjectiveType,值为接收internalId并返回对应QuestObjective的委托
    private static readonly Dictionary<ObjectiveType, Func<string, QuestObjective>> _objectiveCreators = new()
    {
        { ObjectiveType.Fetch, id => new ObjectiveFetch(id) },
        { ObjectiveType.Gather, id => new ObjectiveGather(id) },
        { ObjectiveType.Craft, id => new ObjectiveCraft(id) },
        { ObjectiveType.Deliver, id => new ObjectiveDeliver(id) },
        { ObjectiveType.Combat, id => new ObjectiveCombatEncounter(id) }
    };

    public static QuestObjective Create(ObjectiveType objectiveType, string internalId)
    {
        if (_objectiveCreators.TryGetValue(objectiveType, out var creator))
        {
            return creator(internalId);
        }
        throw new ArgumentOutOfRangeException(nameof(objectiveType), $"不支持的任务目标类型:{objectiveType}");
    }
}
  1. 改造原GenerateQuest方法,调用工厂类创建实例:
protected Quest GenerateQuest(QuestConfiguration questConfiguration)
{
    var objectives = new List<QuestObjective>();
    foreach (var objectiveConfig in questConfiguration.ObjectiveConfigurations)
    {
        objectives.Add(QuestObjectiveFactory.Create(objectiveConfig.ObjectiveType, objectiveConfig.InternalId));
    }
    return new Quest(objectives);
}

优势:

  • 性能与switch相当(字典查找为O(1))
  • 新增任务目标类型时,只需在字典中添加一行映射,无需修改核心逻辑
  • 代码结构清晰,职责分离

方案二:属性标记+反射(适合大量类型场景)

如果任务目标类型非常多,且希望避免手动维护映射字典,可以用反射+自定义属性的方式自动注册类型。

实现步骤:

  1. 定义标记属性,关联子类与ObjectiveType:
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class ObjectiveTypeAttribute : Attribute
{
    public ObjectiveType TargetType { get; }

    public ObjectiveTypeAttribute(ObjectiveType targetType)
    {
        TargetType = targetType;
    }
}
  1. 给每个QuestObjective子类添加该属性:
[ObjectiveType(ObjectiveType.Fetch)]
public class ObjectiveFetch : QuestObjective
{
    public ObjectiveFetch(string internalId) : base(internalId) { }
}

// 其他子类同理
// [ObjectiveType(ObjectiveType.Gather)]
// public class ObjectiveGather : QuestObjective { ... }
  1. 实现工厂类,通过反射自动构建类型映射:
public static class QuestObjectiveFactory
{
    private static readonly Dictionary<ObjectiveType, Type> _typeMapping = new();

    static QuestObjectiveFactory()
    {
        // 扫描当前程序集中所有继承自QuestObjective且带有标记属性的子类
        var objectiveTypes = typeof(QuestObjective).Assembly.GetTypes()
            .Where(t => t.IsSubclassOf(typeof(QuestObjective)) && !t.IsAbstract)
            .Select(t => new 
            { 
                ClassType = t, 
                Attr = t.GetCustomAttribute<ObjectiveTypeAttribute>() 
            })
            .Where(x => x.Attr != null);

        foreach (var item in objectiveTypes)
        {
            _typeMapping.Add(item.Attr.TargetType, item.ClassType);
        }
    }

    public static QuestObjective Create(ObjectiveType objectiveType, string internalId)
    {
        if (_typeMapping.TryGetValue(objectiveType, out var targetType))
        {
            // 假设所有子类都有接收string类型internalId的构造函数
            return (QuestObjective)Activator.CreateInstance(targetType, internalId);
        }
        throw new ArgumentOutOfRangeException(nameof(objectiveType), $"不支持的任务目标类型:{objectiveType}");
    }
}
  1. 同样用改造后的GenerateQuest方法调用工厂即可。

优势:

  • 新增子类时只需添加属性,无需修改工厂逻辑
  • 适合动态加载类型或类型数量极多的场景

注意:

  • 反射初始化首次调用会有轻微性能开销,可通过提前预热优化
  • 若子类构造函数参数变化,需同步调整反射逻辑

总结

如果类型数量不多,优先选方案一,兼顾性能和可维护性;如果类型数量庞大或需要动态扩展,再考虑方案二。两种方案都能彻底消除冗余的switch语句,让代码更易扩展。

内容的提问来源于stack exchange,提问作者vik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:10:48