DEV Community

Souvik
Souvik

Posted on

Tight-coupling and Loose-coupling Implementation in Java

If you are quite familiar with Java and moving towards Spring Framework or you want to get an idea of loosely-coupled and tightly-coupled system in a programming perspective or you want to add a bit more knowledge to your mental knowledge repository, then we are good to go.

What are tightly and loosely coupled systems?

Breifly, tightly-coupled means a system in which the components are dependent on each other. It reduces flexibility of a system and swapping a component for another is very difficult. Loosely-coupled systems are those where components are not dependent on each other and the components can be swapped with ease. So, how do we achieve loose-coupling in Java?

How do we implement loose-coupling in Java?

We achieve this in Java by creating a superior interface. All other classes will implement this interface to define the methods. Its like android apps for the Android software and iOS apps for iOS. Now finally we need a runner class that will instantiate the games and the object of this runner class will be used to run the games from the main class. This might seem a bit overwhelming but stick till the end and you will get the picture.

Tight-coupling Coding Implementation

In the below example, we consider creating a gaming device that will run 2 games: Super Mario and Super Contra. If we implement this in Java, the code will be:

public class SuperMario {  
    public void up() { System.out.println("Super Mario: up"); }  
    public void down() { System.out.println("Super Mario: down"); }  
    public void left() {  System.out.println("Super Mario: left"); }  
    public void right() { System.out.println("Super Mario: right"); }  
}

public class SuperContra {  
    public void up() { System.out.println("Super Contra: up"); }  
    public void down() { System.out.println("Super Contra: down"); }  
    public void left() {  System.out.println("Super Contra: left"); }  
    public void right() { System.out.println("Super Contra: right"); }  
}

public class GameRunner {  
    private SuperMario game;
    public GameRunner(SuperMario game) {  
        this.game = game;  
    }  
    public void run() {  
        game.up();  
        game.down();  
        game.left();  
        game.right();  
    }  
}

public class GamingDevice {  
   public static void main(String[] args) { 
      SuperMario game = new SuperMario(); 
      GameRunner runner = new GameRunner(game);  
      runner.run();  
   }  
}
Enter fullscreen mode Exit fullscreen mode

Now the problem with the above implementation is that in the GameRunner class, the object is strictly set as a SuperMario object. So, currently it seems like our device can only run(tightly-coupled) the SuperMario game. What I mean is, if we try to run the below code in my GamingDevice class, we will get an error.

public class GamingDevice {  
   public static void main(String[] args) { 
      SuperContra game = new SuperContra(); 
      GameRunner runner = new GameRunner(game);  
      runner.run();  
   }  
}
Enter fullscreen mode Exit fullscreen mode

But a device running one game is not ideal right? Our device is supposed to run many games.

To summarize the scenario, our device can currently run only one game now i.e. Super Mario, but we want it to be able to run both Super Mario and Super Contra. So, how do we fix our device?

We fix it by installing a Gaming Software(interface) in our Gaming Device that can run both the games. So, rather than running the game directly on the device, our device will be able to run the gaming software which supports both the games.

So, our new implementation goes like:

Loose-coupling Coding Implementation

public interface GamingSoftware {  
    public void up();  
    public void down();  
    public void left();  
    public void right();  
}

public class SuperMario implements GamingSoftware {  
    public void up() { System.out.println("Super Mario: up"); }  
    public void down() { System.out.println("Super Mario: down"); }  
    public void left() {  System.out.println("Super Mario: left"); }  
    public void right() { System.out.println("Super Mario: right"); }  
}

public class SuperContra implements GamingSoftware {  
    public void up() { System.out.println("Super Contra: up"); }  
    public void down() { System.out.println("Super Contra: down"); }  
    public void left() {  System.out.println("Super Contra: left"); }  
    public void right() { System.out.println("Super Contra: right"); }  
}

public class GameRunner {  
    private GamingSoftware game;  
    public GameRunner(GamingSoftware game) {  
        this.game = game;  
    }  
    public void run() {  
        game.up();  
        game.down();  
        game.left();  
        game.right();  
    }  
}

public class GamingDevice {  
   public static void main(String[] args) { 
      SuperMario superMario = new SuperMario(); 
      SuperContra superContra = new SuperContra();
      GameRunner marioRunner = new GameRunner(superMario);  
      GameRunner contraRunner = new GameRunner(superContra);
      marioRunner.run();
      contraRunner.run();
   } 
}
Enter fullscreen mode Exit fullscreen mode

Now, our both games will run perfectly. So, what we achieved here is a loosely-coupled system or gaming device which will be able to run any game that the Gaming Software supports(i.e. the game is implemented using the GamingSoftware interface). 

So, this is the difference between tightly-coupled and loosely-coupled systems in Java and the difference between their implementations. If you found this article helpful, leave a comment :)

Top comments (0)