Java Swing - How to create the best communication between the model and the view
<p>The biggest issue I deal with when I develop desktop applications using <a href="https://docs.oracle.com/javase/tutorial/uiswing/" rel="nofollow noreferrer">Swing</a> is the spaghetti that I result in when I complete the application.</p>
<p>I come from a PHP background with MVC where I had an easy way to implement dependency injection and I just had access to anywhere in the model layer when I need it, I just constructed the required classes.</p>
<p>But in Java it is a bit more complicated for me, because Swing components are basically little models that do things, the thing is, how do I deal with it to come with a nice and non-spaghetti design.</p>
<p><strong>What I call spaghetti design?</strong></p>
<p>For me, spaghetti design is where I sometimes get to a point that in my component, I need access to a another component, or I need access to somewhere that I don't have it constructed. For this, I need to pass these instances from component to component and that means I create access for for these object(s) for components that will never use it and are just being used as a man in the middle to pass the instance. Basically a point where I ask myself.</p>
<p>Let's look at this dummy example:</p>
<p>You have the component <code>Map</code>. This component should draw you a map of your country, and draw entities (An entity can be just some city label, a military base, an radar target data and anything that a map can display really). So in your model layer you probably have somewhere defined a class named <code>EntitiyManager</code> which contains a list of entities, each entity is something that inherits <code>MapEntity</code>. So what do you have to do in order to draw these entities?</p>
<p><strong>Approach 1</strong></p>
<p>Pass <code>EntityManager</code> to <code>Map</code> and retrieve data from <code>EntityManager</code> to draw:</p>
<pre><code>public class Map extends JPanel {

    /**
     * Entity manager used to store and manipulate entities
     */
    private EntityManager manager;
    
    public Map(EntityManager manager) {
        this.manager = manager;
    }
    
    // SOME CODE HERE ALOT OF CODE
    
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        Graphics2D g2d = (Graphics2D) g;
        
        for (Entity e : manager.getEntities()) {
            if (!e.isVisible()) {
                continue;
            }
            
            if (e instanceof CityLabel) {
                // TO DRAW FOR CITY LABEL
            } else if (e instanceof MilitaryBase) {
                // TO DRAW FOR MILITARY BASE
            }
        }
    }
}
</code></pre>
<p><strong>Approach 2</strong></p>
<p>Pass <code>EntityManager</code> to <code>Map</code> and each <code>Entity</code> will have its own drawing method:</p>
<pre><code>public class Map extends JPanel {

    /**
     * Entity manager used to store and manipulate entities
     */
    private EntityManager manager;

    public Map(EntityManager manager) {
        this.manager = manager;
    }

    // SOME CODE HERE ALOT OF CODE

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;
        manager.render(g2d);
    }
}
</code></pre>
<p><strong>Problem with approach 1:</strong> It's long and messy and is not organized at all, makes your paint method be too big and hard to go through. Even though you can split it into methods.</p>
<p><strong>Problems with approach 2:</strong> <code>EntityManager</code> is not a view, it should not be drawing anything, it should only be used for operations such as algorithms, data management and such.</p>
<p>But in general, I don't like the fact that I passed my <code>EntityManager</code> like this to the view, it just doesn't look good for me.</p>
<p>Now let's say I have to create a function that makes me able to measure distance on the map. I need a <code>mouseEventListener</code> and that mouse event listener needs access to somewhere that it can pass the input to. I need a place to manage that distance measure at. What if I want to create a little window component that shows how many km I measured and on the other side I want to show on the map the dashed line of my measurement, that means I need to use measure distance in two components, these two are related to each other.</p>
<p>I plan to read about <a href="https://projects.spring.io/spring-framework/" rel="nofollow noreferrer">Spring</a> this weekend and see how it can help me.</p>
<p>Another problem that comes to me every time is, I don't really know how I can make my controller pass input to the model correctly, I can't really find a good way to design a controller in Swing because how the components are designed. So for me Input management is also confusing and just makes me do a mess in my program.</p>
<p>So what are good approaches to design a perfect Swing application?</p>
<h1>Update</h1>
<p>My biggest problem comes when I have a view and I have to update another view when something is changed in the current view.</p>
<p>Let's say we have a <code>Map</code> view. The map view is the map of your country. When you move your mouse, you get an event called for that view <code>mouseMoved</code> or something like that, then you get the X, and Y of the mouse in that Map. Now, what we have to do is</p>
<ol>
<li>Convert <code>X</code>, <code>Y</code> to map latitude and longitude which is done in the model for that view,</li>
<li>We have another view which is named <code>BottomInformation</code> which is basically a bar at the bottom of the frame, and it shows information. We need to update the <code>BottomInformation</code> view to show these longitude and latitude we got.</li>
</ol>
<p>This means <code>Map</code> needs access to <code>BottomInformation</code>. How do I do it properly without spaghetti? Are there different approaches than trying MVP and MVC?</p>