我正在用C#开发游戏,我对正确的面向对象设计感到困惑。
在游戏中,3D空间中有节点:
public class Node {
public Vector3 Position;
public Vector3 Size; // etc
}
然后,有一些路径有一个节点数组。节点可以属于多个路径。路径具有与其每个节点相关联的一些数据(“元数据”)。问题是,路径的节点应可访问到其他类,但关联的元数据应保持隐藏。
对于节点和元数据具有不同访问修饰符的两个数组需要工作以使它们保持同步。
将节点与元数据配对的公共包装类型也不是最佳解决方案 - 包装类型仅对路径有意义,因此它不应该是公共的。
将私有数据与公共阵列成员关联的更好方法是什么?
答案 0 :(得分:1)
我可能会误解,但仅仅有两个系列有什么问题?
public class Path {
private NodeInPath[] nodesInPath;
public Node[] nodes;
}
虽然不是将节点与元数据一起包装在像NodeInPath
这样的类中,但在节点及其元数据之间进行映射可能更有用:
public class NodeMetadata {
public Vector3 cameraPosition;
}
public class Path {
private Dictionary<Node, NodeMetadata> _nodeMetadataMapping;
public Node[] nodes;
}
顺便说一下,数组不应该是公共字段。您允许项目在外部进行更改,而无法响应更改。除非每次访问节点时重建此映射,否则它无法适应节点集合中的更改。请参阅this post。
答案 1 :(得分:0)
您必须返回接口INode而不是具体类。在接口上,您只定义允许在路径外访问的方法和属性。路径本身在内部使用具体的类节点,但只返回接口INode。您的代码可能如下所示:
public interface INode {void SomeAccessableMethod(); }
internal class Vector3 {}
internal class Node : INode
{
public void SomeAccessableMethod() {}
public Vector3[] CameraPositions { get; set; }
}
public class Path
{
private readonly IList<INode> _nodesInPath = new List<INode>();
public Path()
{
//Initalise all the nodes
for(int cnt = 0; cnt < 10; cnt++)
{
var node = new Node();
node.CameraPositions = new Vector3[1];
node.CameraPositions[0] = new Vector3();
_nodesInPath.Add(new Node());
}
}
public INode[] NodesInPath
{
get { return _nodesInPath.ToArray(); }
}
}
(我更喜欢使用列表而不是数组,初始化也取决于您。您还可以在路径类中定义Node类。这样就无法在同一个程序集中访问)
答案 2 :(得分:0)
如果我理解正确(我只发布基本结构)。
public class Node {
public Vector3 position;
}
public class Path {
private Dictionary<Node, Vector3> cameraPositions = new Dictionary<node,Vector3>();
public List<Node> NodesInPath {get;}
public Node AddNode(Node node, Vector3 cameraPosition);
public Vector3 GetCameraPosition(Node node);
}
基本上,摄像机位置属于Path类(私有),当您将其添加到路径时,可以单独将其设置为foreach节点。每个路径都有一组给定节点的不同摄像机位置。
答案 3 :(得分:0)
这个想法来自于nmclean的回答和评论:)
嵌套包装类确实是一个很好的解决方案。我使用了一种方法来提供对节点的公共访问。
public class Path {
// wraps a node and its metadata
private class NodeData {
// public members visible only to parent class
public Node Node;
public float SomeMetadata;
}
// private array...
private NodeData[] nodeData;
// ...public method
public Node GetNode(int index) {
return nodeData[index].Node;
}
}