java - Breaking cyclic dependency in constructor -
i'm writing java class manage hex map (class gamemapimpl implements gamemap
) contains cell
objects. cell objects saved in hashmap<hex,cell>
, key position on hex map.
the whole thing used tightly coupled between cells , gamemap, cyclic dependency between two, i'm trying refactor allow more easy testing.
(code below simplified)
public interface gamemap { void hascell(hex hex); void getcell(hex hex); } class gamemapimpl implements gamemap { private map<hex, cell> cellmap; gamemapimpl(set<cell> cells) { cellmap = new hashmap<>(); (cell cell : cells) { // check conditions on cells // ensure map correct, e.g. 1 cell // of particular type // ensures cellmap key cell's position. cellmap.put(cell.position(), cell); } } //obvious implementation hascell , getcell methods }
each cell
needs have hex position
field can own position in gamemap
. in addition, cell
objects need have reference owning gamemap
, perform common useful operations such looking neighbours.
public class cell { final hex position; final gamemap gamemap; cell(hex position, gamemap gamemap) { this.position = position; this.gamemap = gamemap; } public set<cell> getneighbours() { //perform operation needs both gamemap , position } }
the gamemap
built in gamemapbuilder
, provides set<cell>
gamemap
constructor.
public class gamemapbuilder { public gamemap build(...) { // args omitted simplicity set<cells> cells = new hashset<>(); (... : ...) { hex position = calculateposition(...); cell cell = new cell(position, gamemap); } gamemap gamemap = new gamemap(cells); return gamemap; } }
as can see, last snippet of code wrong, because i'm referencing non-existent gamemap
variable. here lies problem: if create gamemap
after initializing cells, cannot pass in cell
's constructor. if opposite, cannot pass set<cells>
gamemap
in order initialize correctly.
does more experienced programmer have idea on how decouple correctly these 2 classes?
alternatively, can go previous tightly coupled design , assume cells exist when gamemap creates them. being these small objects , contained in same package, wouldn't big of deal.
use setter passing gamemap
cell
not constructor. can make package-protected hide other code , call setter in gamemap
constructor or in loop in gamemapbuilder
. known de-frameworks use setters solve circular dependencies.
Comments
Post a Comment