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

如何高效处理相似建筑类并存储,实现属性直接访问?

嘿,我完全懂你纠结的点——要把不同类型的建筑统一存起来方便管理,又不想每次访问专属属性都要强制转换、靠反射或者写一堆switch语句拖慢效率。你提到的用List/Dictionary结合类型键来处理的思路真的很靠谱,我来给你拆解下具体怎么落地这个方案,兼顾灵活性和性能。

第一步:定义基础接口和类型枚举

先搞一个IBuilding接口来统一所有建筑的公共属性,再用枚举区分不同建筑类型,这样后续不管是存储还是创建都有明确的标识:

public enum BuildingType { Farm, Mill, Bakery }

public interface IBuilding
{
    string Name { get; set; }
    float Timer { get; set; }
}

// 实现各自的建筑类
public class Farm : IBuilding
{
    public string Name { get; set; }
    public int CropType { get; set; }
    public float Timer { get; set; }
}

public class Mill : IBuilding
{
    public string Name { get; set; }
    public float Timer { get; set; }
}

public class Bakery : IBuilding
{
    public string Name { get; set; }
    public int ProductionType { get; set; }
    public bool IsOpen { get; set; }
    public float Timer { get; set; }
}

第二步:用Dictionary实现无反射/switch的实例工厂

接下来创建一个工厂类,用Dictionary<BuildingType, Func<IBuilding>>来映射类型到创建实例的委托,这样创建新建筑时直接通过键获取创建逻辑,完全不用switch或者反射:

public static class BuildingFactory
{
    private static readonly Dictionary<BuildingType, Func<IBuilding>> _buildingCreators = new()
    {
        { BuildingType.Farm, () => new Farm { Name = "Default Farm", CropType = 0, Timer = 0f } },
        { BuildingType.Mill, () => new Mill { Name = "Default Mill", Timer = 0f } },
        { BuildingType.Bakery, () => new Bakery { Name = "Default Bakery", ProductionType = 0, IsOpen = true, Timer = 0f } }
    };

    public static T CreateBuilding<T>(BuildingType type) where T : class, IBuilding
    {
        if (_buildingCreators.TryGetValue(type, out var creator))
        {
            return creator() as T;
        }
        throw new ArgumentException($"Unsupported building type: {type}");
    }

    // 通用创建方法,返回IBuilding
    public static IBuilding CreateBuilding(BuildingType type)
    {
        if (_buildingCreators.TryGetValue(type, out var creator))
        {
            return creator();
        }
        throw new ArgumentException($"Unsupported building type: {type}");
    }
}

第三步:用Dictionary+强类型列表高效存储玩家建筑

现在来处理存储问题——用一个Dictionary<BuildingType, object>来存放每种类型的强类型列表,这样既可以统一管理,又能直接获取特定类型的建筑集合,不用强制转换:

public class PlayerBuildingManager
{
    private readonly Dictionary<BuildingType, object> _buildingsByType = new()
    {
        { BuildingType.Farm, new List<Farm>() },
        { BuildingType.Mill, new List<Mill>() },
        { BuildingType.Bakery, new List<Bakery>() }
    };

    // 添加建筑到对应类型的列表
    public void AddBuilding(IBuilding building)
    {
        switch (building)
        {
            case Farm farm:
                ((List<Farm>)_buildingsByType[BuildingType.Farm]).Add(farm);
                break;
            case Mill mill:
                ((List<Mill>)_buildingsByType[BuildingType.Mill]).Add(mill);
                break;
            case Bakery bakery:
                ((List<Bakery>)_buildingsByType[BuildingType.Bakery]).Add(bakery);
                break;
            default:
                throw new ArgumentException($"Unknown building type: {building.GetType().Name}");
        }
    }

    // 强类型获取方法,直接返回对应列表,无需转换
    public List<Farm> GetFarms() => (List<Farm>)_buildingsByType[BuildingType.Farm];
    public List<Mill> GetMills() => (List<Mill>)_buildingsByType[BuildingType.Mill];
    public List<Bakery> GetBakeries() => (List<Bakery>)_buildingsByType[BuildingType.Bakery];

    // 获取所有建筑(用于发送给玩家等场景)
    public IEnumerable<IBuilding> GetAllBuildings()
    {
        foreach (var list in _buildingsByType.Values)
        {
            if (list is IEnumerable<IBuilding> buildings)
            {
                foreach (var building in buildings)
                {
                    yield return building;
                }
            }
        }
    }
}

第四步:实际使用示例

现在你可以在业务代码里这样用,全程高效访问,没有冗余的转换操作:

public class GameServer
{
    private readonly PlayerBuildingManager _playerBuildings = new();

    public void HandlePlayerJoin()
    {
        // 给玩家创建一个农场
        var farm = BuildingFactory.CreateBuilding<Farm>(BuildingType.Farm);
        farm.CropType = 1; // 直接访问专属属性,无需强制转换
        _playerBuildings.AddBuilding(farm);

        // 处理所有磨坊的计时逻辑
        foreach (var mill in _playerBuildings.GetMills())
        {
            mill.Timer += 1f;
            // 直接操作Mill的Timer属性
        }

        // 获取所有建筑发送给玩家
        var allBuildings = _playerBuildings.GetAllBuildings();
        // 序列化allBuildings并发送给客户端
    }
}

为什么这个方案适合你?

  • 无强制转换/反射/switch(创建环节):工厂用委托映射类型,创建实例直接调用委托,性能拉满
  • 高效访问专属属性:通过强类型的Get方法直接拿到对应列表,操作属性不用任何转换
  • 符合开闭原则:新增建筑类型时,只需要加枚举值、实现IBuilding、在工厂和管理器里加对应逻辑,不用修改现有代码
  • 统一管理+灵活处理:既可以通过GetAllBuildings统一获取所有建筑(比如发送给玩家),又能针对单类型建筑做高效逻辑处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:26:00