어떤 '이벤트' 가 일어나는 것을 감시하는 패턴
옵저버 패턴에서는 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들의 내용이 자동으로 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의한다.
데이터가 변경되었을 그 객체를 의존하는 다른 객체들은 데이터를 전달해주는 것을 기다려야 되기 때문에 의존성을 갖는다.
옵저버 또는 리스너(listener)라 불리는 하나 이상의 객체를 관찰 대상이 되는 객체에 등록시킨다.
옵저버들은 관찰 대상인 객체가 발생시키는 이벤트를 받아 처리한다.
느슨한 결합을 이용하면
다른 객체의 상태 변화를 별도의 함수 호출 없이 즉각적으로 알 수 있기 때문에, 이벤트에 대한 처리를 자주 해야 하는 프로그램이라면 매우 효율적인 프로그램을 작성할 수 있다.
다른 클래스를 직접적으로 사용하는 클래스의 의존성을 줄이는 것입니다.
- 리모콘과 TV : TV는 리모컨이 없으면 동작을 못한다
A회사는 로보라는 이름의 로봇을 구매하려고 합니다.
이를 코드로 구현한다면 다음과 같습니다.
class Factory {
buy(Won won) {
return new Robo(won.getDollar()); //Won의 getDollar메서드를 명시적으로 호출
}
}
class Won{
getDollar() {
}
}
위와 같은 코드는 문제를 야기합니다.
만약 회사가 시간이 지나 새로운 로봇을 구매해야 한다고 할 때, 500원짜리 로보가 아닌 일본에서 500엔짜리 로봇을 구매했다고 합시다.
Factory 클래스의 buy메서드는 Won과 강하게 결합되어있기 때문에 아래와 같이
buy메서드를 새로 오버로딩 해주어야 합니다.
class Factory {
buy(Won won) {
return new Robo(won.getDollar());
}
buy(Yen yen) {
return new Robo(yen.getDollar()); // 엔화로 구매할때를 오버로딩
}
}
class Won{
getDollar() {}
}
class Yen {
getDollar() {}
}
작은 프로그램에서는 하나하나 수정하면 되겠지만 프로그램의 규모가 커질 수록
코드를 하나하나 수정하는 것은 위헙합니다.
따라서 getDollar()메서드를 갖는 추상 인터페이스를 선언하고 Won과 Yen이 그를 상속 받도록 하여 객체와 객체간의 결합을 느슨하게 해주어야 합니다.
class Factory {
buy(Payable payable) {
return new Robo(payable.getDollar()); // 원인지 엔화인지 구분하지 않아도됨.
}
}
interface Payable {
getDollar() {}
}
class Won implements Payable{
}
class Yen implements Payable{
}
강한 결합에서는 두 객체간의 인터페이스에서 높은 의존성을 갖고 있어 하나의 객체 변경에서 수많은 객체들의 수정이 필요합니다. 따라서 느슨한 결합을 통해 의존성을 제거하고 시스템을 보다 유연하게 할 필요가 있습니다.