2

Problem

So I'm making a video game and I'm facing a design problem. I would like to pass the reference of a class being constructed to a constructor of another object and pass this other new object to the super constructor of the first class.

Basically something like this:

class B extends A {
    B() {
        super(new C(this));
    }
}

Context

So I have a World class representing the world of my video game. This world can be played and displayed by a WorldScreen. I don't want the World to rely on any WorldScreen. It would be bad design for a world to depend on a screen to be played, the world does not care what technology is used to render its entities and does not care about the UI too. So instead of having the world calling one of WorldScreen's method when the player dies for example, we provide it a WorldEventHandler(observer pattern but only one observer). That WorldEventHandler will take care of keeping a reference to the screen to display the death screen when the player dies or the finish screen etc.

class World { //a video game world
    //notifies about events going on in the world (e.g. the player's death)
    final WorldEventHandler handler; 

    World(WorldEventHandler handler) {
        this.handler = handler;
    }
}

WorldScreen is instantiating a specific WorldEventHandler that will interact with itself.

class WorldScreen {
    final World world;

    WorldScreen() {
        //all good, WorldEventHandlerImpl will interact with WorldScreen whenever needed (display death screen?)
        world = new World(new WorldEventHandlerImpl(this)); 
    }
}

This design is all perfect to me (still open for improvements), the World is not dependant on anything but an interface to listen to its events and the WorldScreen is able to customize its behavior with a specific implementation of that event handler.

The problem comes when I try to do inheritance with WorldScreen. There's many different implementations of WorldScreen that does slightly different things but still lots of things in common regrouped into the abstract WorldScreen class.

abstract class WorldScreen {
    final World world;

    WorldScreen(WorldEventHandler handler) {
        //fine too
        world = new World(handler); 
    }
}

However, as you can see the WorldEventHandler has to be specified by the subclass. It is up to the subclass to decide what to do with world events. So the error occurs when I try to instanciate a WorldEventHandler with a reference to the screen in a subclass:

class OnlineWorldScreen extends WorldScreen {

    OnlineWorldScreen() {
        super(new OnlineWorldEventHandler(this)); //cannot reference 'this' before supertype constructor has been called
    }
}

Workarounds

I've think about 2 workarounds but I hate both of them.

  1. Setting the reference to the screen afterward with a set method:

    • Breaks the model of all my WorldEventHandler for a constructor issue
    • Will do lot of dupplicated code since every implementation will require a set method with a different type to set.
    • The field wasn't meant to be changed initially and I have no other reason to let other programmers think it might be a field that will get changed
  2. Creating an abstract getEventHandler() or buildEventHandler() in WorldScreen to make the super constructor build it when creating the world.

    • What was supposed to be a constructor parameter is now a method
    • That method is meant to be used only once and does basically nothing but a call to a constructor
    • Makes the implementations of WorldScreen heavier

Question

Is there any better workarounds? If not, which is the best and why? If my design is flawed and could be changed into one without that issue, please tell me how instead of presenting a workaround.

Edit

To answer Sebastian Redl's comment, yes it makes sense for the screen to create the world. A screen is the current state of the game, typical examples would be MainMenuScreen, SettingsScreen, LoginScreen etc. So when you go from the MainMenuScreen to the OnlinePlayScreen, it creates the world and play it from your input. It does not make sense to have multiple screens on a single world since it's impossible to have multiple screens at once in the application (using LibGDX framework). The reason I want the World to be 100% standalone is to be able to run one on a server to check if a player is cheating or not. (Taking his inputs and checking if he reaches the same time on server that his client pretended to).

I could make a list of observers instead (not that I need to) but If I would do so, I would make a special implementation of WorldEventHandler that can receive multiple listeners. It's way easier for the World (that is already full with physic engine and game logic) to call a method from an object than looping into a list of 1 elements everytime.

1
  • Your WorldScreen creating the world is very suspicious in the first place. Shouldn't it be possible to have multiple screens displaying the same world? Also, why make the event handler a constructor dependency and thus force exactly one handler? Why not add handlers to the world afterwards and allow multiple handlers? Commented Aug 13, 2017 at 19:10

4 Answers 4

3

You should treat the OnlineWorldEventHandler as a dependency of the OnlineWorldScreen and pass it in. Your problem is immediately solved simply by OnlineWorldScreen taking handler as a parameter. You also gain flexibility by not tying OnlineWorldScreen to OnlineWorldEventHandler. However, this will just push the problem to a different point in the code, but fortunately a point where it's more tractable to handle. Now the problem comes up when you try to create OnlineWorldScreen and OnlineWorldEventHandler. To build one, you need the other.

 OnlineWorldEventHandler handler = new OnlineWorldEventHandler(???);
 OnlineWorldScreen screen = new OnlineWorldScreen(handler);

The typical solution to circular dependency problems (besides redesigning not to have circular dependencies) is lazy evaluation. Here's one approach:

class LazyWorldEventHandler implements WorldEventHandler {
    private Function<WorldScreen, WorldEventHandler> _factory;
    private WorldHandler _handler = null;
    public LazyWorldEventHandler(Function<WorldScreen, WorldEventHandler> handlerFactory) {
        _factory = handlerFactory;
    }
    public void initialize(WorldScreen screen) {
        if(_handler != null) throw new Error("Double initialization");
        _handler = _factory(screen);
        _factory = null;
    }
    // ... implement WorldEventHandler and delegate to _handler
}

You can easily make a generic version of this. It'd probably look (and be) cleaner. Now in some factory method:

LazyWorldEventHandler handler = 
    new LazyWorldEventHandler((WorldScreen screen) -> new OnlineWorldEventHandler(screen));
OnlineWorldScreen screen = new OnlineWorldScreen(handler);
handler.initialize(this);

Tweak as appropriate.

2
  • Since the OnlineWorldEventHandler requires a OnlineWorldScreen specifically, a cast would be required but that's just a detail. Great answer !
    – Winter
    Commented Aug 13, 2017 at 18:10
  • 1
    You could make a more specific Lazy* class to avoid the downcast, or (preferably) parameterize LazyWorldEventHandler by a type parameter replacing WorldScreen, or (even more preferably) just have WorldScreen take a completely parameterized Lazy type, e.g. Lazy<WorldEventHandler>. Commented Aug 13, 2017 at 18:16
0

In your WorldScreen constructor, you could set the WorldScreen implementation's this reference on the handler manually:

WorldScreen(WorldEventHandler handler) {
    handler.setWorldScreen(this);
    world = new World(handler); 
}

And then in your WorldScreen's implementation you would simply call the parent constructor with the appropriate event handler:

OnlineWorldScreen() {
    super(new OnlineWorldEventHandler());
}
1
  • Every WorldEventHandler has a different reference to the screen. One about online interaction need to have a OnlineWorldScreen to do his work. (not just an abstract WorldScreen) I'm not gonna cast it at every use. Taking your idea and pushing this operation down to the subclasses is basically my first workaround.
    – Winter
    Commented Aug 13, 2017 at 15:35
0

Just throwing my 2 cents here, if it were up to me I'd use observer design pattern (https://en.wikipedia.org/wiki/Observer_pattern) where World (subject) would have event dispatcher, and dispatch events when something would happen (player death, end game). This event dispatcher would be exposed for other objects to register their event handlers to.

This would allow WorldScreen to create it's own implementation of event handlers (observers) decoupled from World implementation and then register this event handler to Worlds dispatcher and just wait for triggered events and react to them (e.g player is dead => show "You're dead" screen)

8
  • Best answer so far but It would allow lots of things I do not need. There will always be only one observer to the world. Also, the dispatcher object may be useful if you want to kick out of the World the logic of talking to observers but if I can only have one observer, I'm better simply putting it into the World with a simple setHandler() method and the result would be the same. But... that's exactly the first workaround. If you disagree with that being equivalent to the first workaround I presented, please explain why. Also. why is it better than the second workaround?
    – Winter
    Commented Aug 13, 2017 at 16:07
  • If that's the case (you know there will always be just 1 World and 1 WorldScreen why bother with events and event handler. Just create interface for WorldScreen (and World, maybe) with methods which should be public, and then just create class composed of these 2 interfaces. Then you can pass reference to WorldScreen to World and vice versa.
    – Martin K.
    Commented Aug 13, 2017 at 16:57
  • You got me wrong, there's just one event handler per world but there's lots of different types of screens and event handlers. What I meant is there will never be a need to have multiple observers or listeners listening to the world's events at the same time so I don't need to bother making a list.
    – Winter
    Commented Aug 13, 2017 at 16:59
  • Yeah, that's what's interface for, you don't care what is specific implementation of WorldScreen, you'll just call given methods from World. Event handlers are useful only in case you have unknown amount of listeners.
    – Martin K.
    Commented Aug 13, 2017 at 17:00
  • The event handler is a way to abstract "something that receive events from a world" since the world does not need to run with a screen. (The server even might run a world as fast as he can to check if an uploaded play was legit) I could make the screen implement the WorldEventHandler and that's would be a valid third option. But there is going to be lots of stuff into my screen classes... Those are already managing the UI, game rendering and online interaction.
    – Winter
    Commented Aug 13, 2017 at 17:03
-3

The problem is that your design seams not to implement the MVC-pattern.
Or MVVM or MVP -- call it what you like...

This causes circular dependencies.

Can you explain how the MVC pattern would help in such case? Why is it better? – Winter

It helps to structure dependencies.

What does it requires? – Winter

It requires a clear design of each layer

In this case, the "model" is a complex system with inner events and running on its own.
What would be my controller? – Winter

That's the point. The "complex system with inner events and running on its own" belong to the controller layer working on the model.

The view layer handles interactions with user and/or other systems, "displays" data from the model and calls services in the controller to change data in the model.

How would that relate to a regular data bean? – Winter

Data beans are part of the model layer.

Not every problem has a key-in-hand pattern to blindly apply. – Winter

The MVC pattern is something very basic like the input - process - output paradigm. You don't need to follow it (blindly) but if you do it saves you from a lot of trouble, especially the "circular dependency" kind.

10
  • 1
    Can you explain how the MVC pattern would help in such case? Why is it better? What does it requires? In this case, the "model" is a complex system with inner events and running on its own. How would that relate to a regular data bean? What would be my controller? Not every problem has a key-in-hand pattern to blindly apply.
    – Winter
    Commented Aug 13, 2017 at 15:24
  • Never heard of MVVC or MCP. Perhaps you meant MVVM and MVP. Also not sure if those design patterns would solve anything in this case. Could you provide an example?
    – Jan Sommer
    Commented Aug 13, 2017 at 16:13
  • @Winter updated the answer Commented Aug 13, 2017 at 17:46
  • @JanSommer Names are just dust n the wind... Commented Aug 13, 2017 at 17:46
  • My point with the World object was that there's no data bean involved. There's no model to work on. I do not need an explanation on how MVC works. Your answer is not helpful and does not take the question in consideration.
    – Winter
    Commented Aug 13, 2017 at 17:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.