Reputation: 61
I'm making a 2D game in Java.
I have this Java scheme :
| Map | ---- | BlockGrid | ---- | Block |
where Map, BlockGrid and Block are Java classes.
Here, the Map class has a BlockGrid attribute and the BlockGrid class has a Block[ ][ ] attribute storing all the blocks in the grid.
I want to be able to access methods in my Map instance from my Block class.
For example, I want to call spawnEntity(..)
on the Map instance to spawn an Arrow or something.
I thought about making spawnEntity(..)
static but I know it is not a good practice since in order to spawn an entity, the Map need to be instanciated.
I also thought about passing my Map instance as parameter in each constructor. That way, BlockGrid and Block would have access to the instance and would be able to call methods.
What is the best practice for this case ? Thank you.
Upvotes: 3
Views: 175
Reputation: 3311
Generally, a good practice is to have loose coupling of unrelated components. This means that if you choose to make the methods of your Map
class available to the Block
class by passing down references you should consider doing that via an interface (see Omars answer). This way you can initialize your Block
s with objects of other classes instead of just Map
instances if you later choose to do so.
But the second thing you should ask yourself if it really is a Block
s responsibility to be able to spawn entities? I would say no because a Block
is probably just a representation of a location plus some structure (although I don't know the semantics of your program). By choosing a different way to structure your programm you avoid introducing circular dependencies (Map
depends on Block
, Block
depends on Map
) which are usually considered a really bad thing (among other things, because you get a high coupling of your components) and follow the Single responsibility principle (because Block
s are not responsible any longer for spawning entities).
In my opinion, you shouldn't allow accessing Map
s from Block
s but instead make it Map
responsibility to spawn entities. One way of doing it would be:
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 {}
Upvotes: 1
Reputation: 301
Make an interface:
interface EntitySpawner {
void spawnEntity(...);
}
Make your Map
class implement this interface, then make BlockGrid
accept EntitySpawner
as an argument.
class Map implements EntitySpawner {
private final BlockGrid grid = new BlockGrid(this);
@Override
public void spawnEntity(..) {
// do something here
}
}
Upvotes: 0