Tight Coupling vs Loose Coupling in Java

 🔍 What is Coupling in Java?

Coupling refers to the degree of dependency between two classes or modules.

  • 🤝 Tight Coupling = Classes are strongly dependent on each other.
  • 🪢 Loose Coupling = Classes are independent and interact via abstraction.

🚨 Tight Coupling (Bad Design Practice)

A tightly coupled class knows too much about another class. Changes in one class can break the other.

🔧 Example: Tight Coupling

class Engine {
public void start() {
System.out.println("Engine started");
}
}

class Car {
Engine engine = new Engine(); // Direct dependency

public void drive() {
engine.start();
System.out.println("Car is driving");
}
}

❌ Problems:

  • You can’t switch to another engine easily (e.g., ElectricEngine).
  • Hard to unit test Car without initializing Engine.
  • Changes in Engine might break Car.

✅ Loose Coupling (Preferred Approach)

In a loosely coupled design, classes depend on abstractions (interfaces), not concrete implementations.

🌟 Benefits of Loose Coupling:

  • Easy to test (you can mock dependencies).
  • Easy to extend or replace components.
  • Promotes cleaner design and maintainability.

🔧 Example: Loose Coupling with Interface

interface Engine {
void start();
}

class PetrolEngine implements Engine {
public void start() {
System.out.println("Petrol engine started");
}
}

class Car {
private Engine engine;

// Inject engine via constructor
public Car(Engine engine) {
this.engine = engine;
}

public void drive() {
engine.start();
System.out.println("Car is driving");
}
}

✅ Usage

public class Main {
public static void main(String[] args) {
Engine engine = new PetrolEngine();
Car car = new Car(engine);
car.drive();
}
}

🔧 How Spring Framework Promotes Loose Coupling

Spring achieves loose coupling using:

  • Dependency Injection
  • Interfaces and Annotations (@Autowired, @Service, etc.)
  • IoC Container (Inversion of Control)

You don’t create dependencies manually — Spring injects them for you.

🔁 Real Example Using Spring Boot

public interface NotificationService {
void send(String message);
}

@Service
public class EmailService implements NotificationService {
public void send(String message) {
System.out.println("Email sent: " + message);
}
}

@RestController
public class NotificationController {

private final NotificationService service;

@Autowired
public NotificationController(NotificationService service) {
this.service = service;
}

@GetMapping("/notify")
public String notifyUser() {
service.send("Welcome!");
return "Notification sent!";
}
}
You can easily swap EmailService with SmsService — the controller doesn’t need to change at all!

🔍 Summary: Tight vs. Loose Coupling

Final Thoughts

  • Avoid tight coupling whenever possible.
  • Embrace interfaces, dependency injection, and composition.
  • Spring Boot helps you build loosely coupled, maintainable applications by default.
💡 Tight coupling makes your code rigid. Loose coupling makes it adaptable.

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare