Tight Coupling & Loose Coupling

Talking about Java and Spring we need to understand the techniques of Tight Coupling and Loose Coupling.

We will focus on these terms for the Java umbrella. First review the Tight Coupling and then the Loose Coupling techniques.

Tight Coupling

This technique happens when the classes are dependent on specific classes, creating a dependency, in other words when the code creates an instance of the dependency inside the class. So, if we need change the classes (maybe for an improvement, or an different process) is necessary modify the classes that has the dependencies.

This can be explained in the below code.

class TightCoupling {
//Here is where the tight Coupling
MyClass myClass = new MyClass();
public void executeMethod()
{
myClass.doSomething();
}
}
class MyClass {
public void doSomething()
{
System.out.println("Tight coupling concept");
}
}

In the code, we can see that we have two classes: TightCoupling and MyClass, here the TightCoupling class is instantiating an object of MyClass, this means that MyClass is a dependency of TightCoupling. We can see that because in line 4, an instance of the MyClass is created and assigned to myClass reference.

Imagine that have a class that makes coffee called CoffeeMaker and the class have a dependency of a class called BlackCoffee, Then we can say the Coffee Maker makes only black coffee.

public class CoffeMaker {
  BlackCoffee blackCoffe =
new BlackCoffee();
  //.. More methods and variables
}

public class BlackCoffee {
  //.. More methods and variables
}

The problem arise when the CoffeMaker class need to make cappuccino, instead of black coffee. so, enable this change we need to modify the code in CoffeMaker, in order to crete now cappuccino.

public class CoffeMaker {
  Cappuccino cappuccino =
new Cappuccino();
  //.. More methods and variables
}

public class Cappuccino {
  //.. More methods and variables
}

This technique is not wrong because is the way that we instantiate the objects in java, but if we want to use frameworks, design patterns, etc. we need to reduce the use of this technique, because this would be a disadvantage of using tightly coupled code.

Loose Coupling

This technique occurs when the classes are not dependent on specific classes but on interfaces. Loose coupling says that is better way to implement an interface. In this technique instead of create a dependency directly, we ask for the class that we can use in the argument of the constructor.

The below code illustrates the Loose Coupling:

// This code illustrate the loose coupling concept
public interface MyInterface {
void doSomenthing();
}
class MyClass implements MyInterface {
public void doSomenthing(){
System.out.println("I am doing something from My Class");
}
}
class MyOtherClass implements MyInterface {
public void doSomenthing() {
System.out.println("doSomething");
}
}
public class LooseCoupling {
MyInterface myInterface;
public LooseCoupling(MyInterface myInterface){
this.myInterface = myInterface;
}
public static void main(String[] args) {
/*Here is where the Loose Coupling occurs, we have the class declaration and class
instantiation using the interface and the class*/
LooseCoupling looseCoupling = new LooseCoupling(new MyOtherClass());
looseCoupling.doSomenthing();
}
}

The code has an Interface called MyInterface and the class LooseCoupling and MyClass that implements MyInterface.

In the line 38, we are creating the dependency, but we ask which class we need to use.

Let’s revisit the Coffee Maker example. We mentioned before that a problem arises when the CoffeMaker class need to make more types of coffee. Let’s review an improvement of the code.

public interface Coffee {
  //Method declarations
}

public class Cappuccino implements Coffee {
  //Implemented interface methods
}

public class BlackCoffee implements Coffee {
  //Implemented interface methods
}

public class CoffeMaker {
  Coffee coffee;

public CoffeMaker(Coffee coffee){
   this.coffee = coffee;
}

//.. More methods and variables

public static void main(String[] args){
CoffeeMaker coffeeMaker = new CoffeeMaker(new Cappuccino());
//...
}
}

By injecting the Cappuccino object into the CoffeeMaker class, we achieve a decoupled design (Loose Coupling) where the CoffeeMaker class is not dependent on a specific coffee type. This allows us to easily change the coffee type as needed and even add more coffee types in the future.

What do you think about these two techniques? any of them are bad but their use is based on the context. If you are planning to use the Spring Framework the best is understand this two techniques.

Thanks for reading and Happy Learning!!!

Leave a comment