我正在用Java制作2D游戏。
我有这个Java方案:
| Map | ---- | BlockGrid | ---- | Block |
其中Map,BlockGrid和Block是Java类。
在这里,地图类具有 BlockGrid属性,而 BlockGrid类具有 Block [] []属性将所有块存储在网格中。
我希望能够从我的Block类访问Map实例中的方法。
例如,我想在Map实例上调用spawnEntity(..)
以生成箭头或其他东西。
我曾考虑过使spawnEntity(..)
静态,但是我知道这不是一个好习惯,因为要生成实体,需要实例化地图。
我还考虑过将 Map实例作为参数传递给每个构造函数。这样,BlockGrid和Block可以访问实例并可以调用方法。
此案例的最佳做法是什么? 谢谢。
答案 0 :(得分:1)
通常,一个好的实践是拥有loose coupling个无关的组件。这意味着,如果您选择通过向下传递引用使Map
类的方法对Block
类可用,则应考虑通过接口进行此操作(请参阅Omars答案)。这样,您便可以使用其他类的对象而不是Block
实例来初始化Map
,如果以后选择这样做的话。
但是第二件事,您应该问自己,是否能够真正产生实体是Block
的责任?我会说 no ,因为Block
可能只是位置加上某种结构的表示(尽管我不知道您程序的语义)。通过选择另一种结构化程序的方式,可以避免引入circular dependencies(Map
取决于Block
,Block
取决于Map
),这些通常被认为是坏事情(除其他事项外,因为您得到了组件的高耦合)并遵循Single responsibility principle(因为Block
对生成实体不再负责)。
我认为,您不应允许从Map
访问Block
,而应由Map
负责产生实体。一种方法是:
public final class Map {
private final BlockGrid blockGrid;
public Map(BlockGrid grid) {this.blockGrid = grid;}
public void spawnEntityAt(int x, int y) {
Block block = this.blockGrid.getBlockAt(x, y);
// spawn the entity using information from 'block'
}
}
final class BlockGrid {
private final Block[][] grid;
public BlockGrid(Block[][] grid) { this.grid = grid; }
public Block getBlockAt(int x, int y) {
return this.grid[x][y];
}
}
final class Block {}
答案 1 :(得分:0)
建立界面:
interface EntitySpawner {
void spawnEntity(...);
}
让您的Map
类实现此接口,然后使BlockGrid
接受EntitySpawner
作为参数。
class Map implements EntitySpawner {
private final BlockGrid grid = new BlockGrid(this);
@Override
public void spawnEntity(..) {
// do something here
}
}