2017-06-04 36 views
-1

我正在使用C#编程项目,对于OOP最佳实践我有两个问题。为了简化问题,我简化了代码示例。面向嵌套类和帮助函数的OOP最佳设计实践

我有一个类Map它将信息保存到2D瓦片地图。将只有一个地图类的实例:

class Map { 
    int height 
    int width 
    InventoryGrid iGrid 
    TileGrid tGrid 

    public Map(int height, int width) { ... } 
} 

Map类包含2点涉及地图上的项目和瓷砖的网格。这些是技术上嵌套的类,因为它们不会在代码中的其他任何地方初始化。例如,InventoryGrid类可能是这样的:

class InventoryGrid { 
    Dictionary<int, Item> inventory 

    public function SetInventory(int index, item) { ... } 
    public function GetInventory(int index) { ... } 
} 

假设我们有一个Job类的情况下,动作完成后需要更新库存。

class Job { 
    public void FinishedJob() 
    { 
     // I need to update the inventory. 
    } 
} 

让我们假设Job类使得事件的呼叫或访问该Map实例。

第一个问题是,什么是最好的OO方式来调用内部类的InventoryGrid.SetInventory()函数:

  1. Map类创建一个getter函数并调用map.iGrid.SetInventory ()直接。
  2. Map类中创建一个新函数,例如map.SetInventoryAt(),该函数继而调用iGrid.SetInventory()函数。
  3. 其他解决方案?

现在在我们的例子中,地图需要x和y坐标。然而,“网格”采用一个唯一的确定性索引来存储他们的信息。需要将坐标转换为索引的函数。

public int CoordsToIndex(int x, int y) {...} 

此功能将所有网格使用(InventoryGrid,TileGrid,等...)

我的第二个问题是,根据最佳实践OO设计应该在哪里居住功能?谁是责任呢?

  1. 我是否创建超类Grid包含所有“网格”继承的函数以避免重复?特定于C#:使用接口而不是超类?
  2. 我是否把它放在Map班,并指出“网格”不应该意识到索引转换的坐标。这会影响第一个问题吗?
  3. 我是否会制作一个名为GridTools的单独(静态)类,该类包含辅助方法?
  4. 其他解决方案?

回答

0

我会去a)#2和b)#1的选择。

如果Map是一个Singleton使它静态。

a)#2因为getter提供库存是一个成员,所以一个函数可以给你更多的封装,并且在将来可以利用继承和接口扩展对象模型。 Getter的套装单值比嵌套类要好得多。 编辑:我看到你正在通过iGrid访问获取者,#1,这是不是很明显打电话给你这是如何设置库存。国际海事组织这将是同样可以接受的解决方案,使用暴露的iGrid,如果它被命名为InventoryGrid。如果你有子嵌套类,这将是一个更好的方法。

b)#1因为在逻辑上避免重复在2个网格类需要相同方法的场景中,基类/超类是最好的方法之一。如果它们具有实现特定的功能,则可以选择每个网格来实现接口,如果这种情况也可以使用抽象基本方法。

此功能将所有网格使用(InventoryGrid,TileGrid,等...)

我认为,虽然这两个电网将共享这InventoryGrid完全相同的实施和一个CoordsToIndex基类而TileGrid就是你现在想要的(在你的设计中的这一点上)。我假设CoordsToIndex依赖于两个网格中的数据,否则你的解耦和将CoordsToIndex放入Map类的想法是个好主意。

随着Helper类让他们多为应用广泛的东西:配置,文件,加密,日志/追踪,扩展方法等

你的顶部2个选择这两种方案都不错,所以你在正确的轨道上。一个建议是,接口允许你使用单元测试模拟,所以你可能想写几个单元测试来确认你可以测试你的oop体系结构。

0

回答你的第一个问题,谷歌“德米特法”。这将给你很好的面向对象的准则。请记住,这是一个指导方针,而不是一个硬性规则。

要回答第二个问题,请将翻译代码放在Map类上,因为这是最简单的解决方案,您可以稍后重构。如果你发现你需要一堆相关的助手,可以创建一个新的助手类并在那里移动逻辑。如果您发现其他组件需要访问映射,则创建一个基本映射类并在其中移动逻辑。总是选择最基本的解决方案,因为当更好的解决方案变得更加清晰时(Google YAGNI),它是最容易改变的解决方案。

也就是说,考虑使用多维数组或锯齿形数组而不是Dictionary。对我来说,他们更容易理解瓷砖地图,并且翻译问题消失。解决问题比解决问题更好。