Search code examples
javadesign-patternslambdaencapsulation

Is bad design sign to return a lambda that breaks encapsulation


I have a Game class that needs some resources that are produced by Generators classes. Every game has its own generators and because generators are heavy objects to instantiate, Game keeps an object pool with instances. In every Generator I have methods like these:

private MapBoardGenerator(Game game) {
    super(game);
}

public static MapBoardGenerator getInstance(Game game) {
    MapBoardGenerator instance = game.getGenerator(MapBoardGenerator.class);
    if (instance == null) {
        instance = new MapBoardGenerator(game);
        game.addGenerator(MapBoardGenerator.class, instance);
    }
    return instance;
}

This static method is almost identical in every class that extends Generator.

What I want to do is provide a Supplier<MapBoardGenerator> to game so the controls will be made elsewhere and getInstance method will simply be:

public static MapBoardGenerator getInstance(Game game) {
    return game.getInstance(MapBoardGenerator.class, MapBoardGenerator::new);
}

Is something wrong if I pass a supplier that calls a private constructor? It's a university project and design matters a lot here.


Solution

  • Passing a private constructor as an instance of Supplier does not break encapsulation, for the very reason that the constructor is passed as an instance of Supplier. The receiver of the instance (in this case Game) has no idea how the Supplier is implemented, only that it fulfills the Supplier interface. That's what Programming to an Interface is all about: even though the caller provides a concrete implementation, the receiver is only aware of the interface which the implementation fulfills. Encapsulation would be violated if the Game knew the specific implementation that it was getting.

    Note that passing a Supplier to the Game may or may not make sense in the larger context of your application, but at least it does not violate the encapsulation of MapBoardGenerator.