결합도(Coupling)는 한 객체가 다른 객체에 얼마나 의존하고 있는지를 나타내는 개념입니다. 두 객체가 서로 완전히 독립적이라면, 한쪽에서 발생한 변경이 다른 쪽에 영향을 주지 않습니다. 이처럼 객체 간의 의존성이 낮은 상태를 느슨한 결합(Loose Coupling)이라고 부릅니다.
반대로 한 객체의 변경이 다른 객체에 직접적인 영향을 미치는 경우에는 긴밀한 결합(Tight Coupling)이라 하며, 이는 코드 유지보수성과 확장성을 떨어뜨리는 요인이 됩니다.
자바에서 느슨한 결합을 구현하는 방법
자바에서는 인터페이스(Interface)를 활용하면 느슨한 결합을 쉽게 달성할 수 있습니다. 구체적인 구현 클래스가 아닌 인터페이스 타입으로 객체를 참조하면, 실제 사용되는 구현체가 바뀌더라도 코드 수정 없이 유연하게 대응할 수 있습니다.
예제 코드
아래 예제에서는 Animal 인터페이스를 정의하고, Cat과 Dog 클래스가 각각 이를 구현합니다. 메인 클래스에서는 인터페이스 타입 변수로 객체를 참조하기 때문에, 나중에 Dog로 교체해도 나머지 코드는 전혀 변경할 필요가 없습니다.
interface Animal {
void child();
}
class Cat implements Animal {
public void child() {
System.out.println("kitten");
}
}
class Dog implements Animal {
public void child() {
System.out.println("puppy");
}
}
public class LooseCoupling {
public static void main(String args[]) {
Animal obj = new Cat();
obj.child();
}
}
실행 결과
kitten
위 코드에서 Animal obj = new Cat(); 부분을 Animal obj = new Dog();로 바꾸면 출력 결과가 puppy로 변경됩니다. 이처럼 인터페이스를 통한 참조는 구현 클래스와 사용 코드 사이의 의존성을 끊어주므로, 느슨한 결합의 핵심 원리라고 할 수 있습니다.
느슨한 결합의 장점
- 유지보수성 향상: 특정 모듈의 변경이 다른 모듈에 미치는 영향을 최소화할 수 있습니다.
- 테스트 용이성: 인터페이스 기반 설계는 목(Mock) 객체를 활용한 단위 테스트를 쉽게 만들어 줍니다.
- 확장성 확보: 새로운 구현체를 추가하더라도 기존 코드를 수정하지 않고 기능을 확장할 수 있습니다.
- 재사용성 증대: 구현과 사용이 분리되어 있어 컴포넌트를 다른 곳에서도 재사용하기 좋습니다.
결론적으로, 느슨한 결합은 객체 지향 설계에서 시스템의 유연성과 안정성을 높이는 중요한 원칙입니다. 자바에서는 인터페이스와 추상화를 적극적으로 활용하여 이를 효과적으로 구현할 수 있습니다.