Tight Coupling and Loosely Coupled Concepts
Introduction
Tight coupling refers to a concept in Java that denotes a strong relationship between classes. When changes are made to the logic or if one class encounters an error, it affects all other related classes.
Loosely coupled implies reducing dependency between classes.
Easy-to-Understand Example
Consider this example:
Suppose you have a class that executes a highly complex task, one of which is sorting data before processing.
public class BubbleSortAlgorithm {
public void sort(int[] array) {
// TODO: Add your logic here
System.out.println("Sorted using bubble sort algorithm");
}
}
public class VeryComplexService {
private BubbleSortAlgorithm bubbleSortAlgorithm = new BubbleSortAlgorithm();
public VeryComplexService(){}
public void complexBusiness(int array[]) {
bubbleSortAlgorithm.sort(array);
// TODO: more logic here
}
}
With this approach, VeryComplexService
accomplishes its task. However, if there is a request to change the sorting algorithm to QuickSort, it seems we'll need to entirely modify both classes.
Furthermore, BubbleSortAlgorithm
will only exist if VeryComplexService
exists since VeryComplexService
creates the BubbleSortAlgorithm
object internally (or in other words, the existence of BubbleSortAlgorithm
is determined by VeryComplexService
). In this implementation, they are tightly coupled.
Intermediate Solution:
public interface SortAlgorithm { void sort(int array[]); } public class BubbleSortAlgorithm implements SortAlgorithm { @Override public void sort(int[] array) { // TODO: Add your logic here System.out.println("Sorted using bubble sort algorithm"); } } public class VeryComplexService { private SortAlgorithm sortAlgorithm; public VeryComplexService() { sortAlgorithm = new BubbleSortAlgorithm(); } public void complexBusiness(int array[]) { sortAlgorithm.sort(array); // TODO: more logic here } }
With this approach, VeryComplexService
is related only to the SortAlgorithm
interface. Though this reduces the relationship, it doesn't change the fact that the algorithm being used is still BubbleSortAlgorithm
.
Advanced Solution:
public interface SortAlgorithm {
void sort(int array[]);
}
public class BubbleSortAlgorithm implements SortAlgorithm {
@Override
public void sort(int[] array) {
// TODO: Add your logic here
System.out.println("Sorted using bubble sort algorithm");
}
}
public class QuicksortAlgorithm implements SortAlgorithm {
@Override
public void sort(int[] array) {
// TODO: Add your logic here
System.out.println("Sorted using quicksort algorithm");
}
}
public class VeryComplexService {
private SortAlgorithm sortAlgorithm;
public VeryComplexService(SortAlgorithm sortAlgorithm) {
this.sortAlgorithm = sortAlgorithm;
}
public void complexBusiness(int array[]) {
sortAlgorithm.sort(array);
// TODO: more logic here
}
}
public static void main(String[] args) {
SortAlgorithm bubbleSortAlgorithm = new BubbleSortAlgorithm();
SortAlgorithm quickSortAlgorithm = new QuicksortAlgorithm();
VeryComplexService business1 = new VeryComplexService(bubbleSortAlgorithm);
VeryComplexService business2 = new VeryComplexService(quickSortAlgorithm);
}
This third approach is the most common. The relationship between the two classes is much looser now. VeryComplexService
no longer cares about the sorting algorithm, focusing only on the business logic. The SortAlgorithm
is provided externally based on the specific usage needs.
Dependency Injection
Once you grasp the concepts of tight coupling and loosely coupled, understanding Dependency Injection becomes easier. It's one of the key factors that brighten up your Java programming journey.
Conclusion
Writing code to make it run is simple, but to ensure code's extensibility and maintainability is quite a challenge. We'll delve into more object-oriented programming concepts in the following articles.