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

C#控制台游戏地图对象创建:如何解耦工厂模式实现?

C# 游戏对象工厂解耦方案

问题场景

我正在开发一款C#控制台游戏,需读取文件生成的地图。读取文件内容为字符串后,逐个解析字符并通过工厂模式创建对应对象。现有基类Object,派生了Box、Wall、Grass、Tree等子类,每个子类通过重写只读属性Model定义游戏显示字符,且在构造函数中设置MapCharacter对应文件中的标识字符。当前工厂类使用switch语句根据MapCharacter创建对象,新增子类时需修改switch,存在耦合问题。曾考虑用反射获取子类信息,但认为该方案不够优雅,希望寻求更优的解耦实现方式。

方案1:静态注册机制(可控性强,无反射)

让每个子类自行注册到全局映射表,工厂直接从映射表获取创建逻辑,新增子类时仅需修改子类代码,无需改动工厂。

修改基类,添加注册逻辑

public abstract class Object
{
    public abstract char Model { get; }
    public string Name { get; protected set; }
    public char MapCharacter { get; protected set; }
    // 其他属性(Colors、Destructible等)省略...
    public abstract void OnDestroy();

    // 全局映射表:地图字符 → 对象创建委托
    private static readonly Dictionary<char, Func<Object>> _objectCreators = new();

    // 子类调用的注册方法
    protected static void RegisterObject(char mapChar, Func<Object> creator)
    {
        if (!_objectCreators.ContainsKey(mapChar))
        {
            _objectCreators.Add(mapChar, creator);
        }
    }

    // 供工厂调用的实例创建入口
    public static Object CreateFromMapChar(char mapChar)
    {
        _objectCreators.TryGetValue(mapChar, out var creator);
        return creator?.Invoke();
    }
}

子类添加静态构造函数完成注册

public class Box : Object
{
    public override char Model => '■';

    // 静态构造函数,程序启动时自动执行注册
    static Box()
    {
        RegisterObject('B', () => new Box());
    }

    public Box()
    {
        Name = "box";
        MapCharacter = 'B';
        Colors = new List<ConsoleColor> { ConsoleColor.DarkYellow };
        Destructible = true;
        Passable = false;
        SeeThrough = false;
        Health = 200;
    }

    public override void OnDestroy()
    {
    }
}

简化工厂类

public class ObjectFactory : IObjectFactory
{
    public Object GetObject(char mapCharacter)
    {
        return Object.CreateFromMapChar(mapCharacter);
    }
}

方案2:特性标记 + 启动扫描(低耦合,少量反射)

用特性标记子类对应的地图字符,程序启动时一次性扫描所有子类构建映射表,比直接在工厂中反射创建更高效。

定义映射特性

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class MapCharacterAttribute : Attribute
{
    public char Character { get; }

    public MapCharacterAttribute(char character)
    {
        Character = character;
    }
}

子类添加特性标记

[MapCharacter('B')]
public class Box : Object
{
    public override char Model => '■';

    public Box()
    {
        Name = "box";
        Colors = new List<ConsoleColor> { ConsoleColor.DarkYellow };
        Destructible = true;
        Passable = false;
        SeeThrough = false;
        Health = 200;
    }

    public override void OnDestroy()
    {
    }
}

工厂类实现扫描与创建

public class ObjectFactory : IObjectFactory
{
    private readonly Dictionary<char, Type> _objectTypes = new();

    public ObjectFactory()
    {
        // 扫描当前程序集中所有继承自Object的非抽象类
        var objectTypes = typeof(Object).Assembly.GetTypes()
            .Where(t => typeof(Object).IsAssignableFrom(t) && !t.IsAbstract);

        foreach (var type in objectTypes)
        {
            var attr = type.GetCustomAttribute<MapCharacterAttribute>();
            if (attr != null && !_objectTypes.ContainsKey(attr.Character))
            {
                _objectTypes.Add(attr.Character, type);
            }
        }
    }

    public Object GetObject(char mapCharacter)
    {
        if (_objectTypes.TryGetValue(mapCharacter, out var type))
        {
            return (Object)Activator.CreateInstance(type);
        }
        return null;
    }
}

方案3:依赖注入容器(适合大型项目)

如果项目已使用DI容器(如Autofac、Microsoft.Extensions.DependencyInjection),可将所有Object子类注册到容器,工厂从容器获取实例,进一步解耦创建逻辑。

注册服务(以Microsoft DI为例)

var services = new ServiceCollection();
// 注册所有Object子类为瞬时服务
services.AddTransient<Box>();
services.AddTransient<Tree>();
services.AddTransient<Wall>();
services.AddTransient<Grass>();
// 注册工厂
services.AddSingleton<IObjectFactory, ObjectFactory>();

var provider = services.BuildServiceProvider();

DI版工厂实现

public class ObjectFactory : IObjectFactory
{
    private readonly IServiceProvider _serviceProvider;
    private readonly Dictionary<char, Type> _objectTypeMap = new()
    {
        {'B', typeof(Box)},
        {'T', typeof(Tree)},
        {'W', typeof(Wall)},
        {'G', typeof(Grass)}
    };

    public ObjectFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public Object GetObject(char mapCharacter)
    {
        if (_objectTypeMap.TryGetValue(mapCharacter, out var type))
        {
            return (Object)_serviceProvider.GetService(type);
        }
        return null;
    }
}

若想进一步解耦映射表,可结合方案2的特性扫描逻辑,在工厂构造函数中自动生成_objectTypeMap,无需手动维护字典。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:20:35