티스토리 뷰

donaricano-btn
반응형

루이스는 최고의 개발자가 되기 위해 수련을 이어가던 중 통장 잔고가 바닥나는 불운을 겪게 되었습니다. 그는 생활비를 마련하기 위해 어쩔 수 없이 편의점 야간 알바를 시작하게 되었죠. 하지만 낮에는 개발 공부를 하고 밤에는 아르바이트를 하는 생활이 결코 쉽지는 않았습니다. 특히 잠이 부족한 것이 항상 문제였죠.

 

루이스는 지난 한 달 간의 아르바이트 경험으로 새벽 2시 정도가 지나면 손님이 거의 오지 않는다는 사실을 파악했습니다. 손님이 없는 동안에는 창고나 카운터 의자에 앉아 잠깐 눈을 붙일 수 있을 것입니다. 하지만 손님이 오면 얼른 나와서 업무를 시작해야겠죠. 만약 손님이 왔는데도 계속 잠을 자고 있다면 그는 알바를 잘리고 말것입니다.

 

루이스는 자신의 특기를 살려 손님이 문을 열고 들어오면 자신이 쪽잠을 자고 있는 창고나 카운터 구석 의자에 알람이 울리도록 하는 프로그램을 만들고자 합니다. 이 프로그램만 완성하면 알바를 잘리지도 않고 부족한 수면시간도 채울 수 있겠죠. 루이스가 만든 프로그램의 코드를 잠깐 살펴볼까요?

 

public class Door {

    // 인스턴스 변수 선언

    public void open() {
        // 손님이 문을 열고 들어옴
        store.alarm();
        counter.alarm();
    }
}

 

코드는 아주 간단합니다. Door객체에서 open() 메소드가 호출 되면, 즉 문이 열리면 창고(store)와 카운터(counter)에 알람이 울리게 되는거죠. 루이스는 이 프로그램을 통해 한동안 꿀잠을 잘 수 있었습니다. 그러나 문제가 생기고 말죠. 사장님이 알바 감시용 CCTV를 통해 카운터에서 졸고있는 루이스를 발견하고 한 번만 더 졸다가 걸리면 해고해 버리겠다고 으름장을 놓았기 때문입니다.

 

아쉽게도 위 프로그램에서 counter 객체는 제거해야 할 것 같습니다. 하지만 루이스는 카운터 의자 말고도 또 다른 꿀잠 포인트를 이미 확보해 두고 있었죠. 손님들이 음식을 먹는 테이블 중 하나가 매대에 가려 CCTV에 사각지대 안에 속해 있었던 것이죠. 그래서 루이스는 프로그램에 table 객체를 추가하려고 합니다.

 

하지만 매번 이렇게 꿀잠 포인트를 바꿀 때 마다 코드를 일일히 수정해야 하는 것일까요? 루이스는 조금 더 쉽게 꿀잠 포인트를 추가하고 제거할 수 있는 코드를 고민하다가 다음과 같은 코드를 완성했습니다.

 

public interface Observer {
    public void alarm();
}

public class Table implements Observer {

    @Override
    public void alarm() {
        // 알람이 울립니다.
    }
}

public class Store implements Observer {

    @Override
    public void alarm() {
        // 알람이 울립니다.
    }
}

public interface Subject {
    public void registerObserver(Observer observer);
    public void removeObserver(Observer observer);
    public void notifyObservers();
}

public class Door implements Subject {
    
    // 인스턴스 변수 선언
    private List<Observer> observers = new ArrayList<>();
    
    public void open() {
        // 손님이 문을 열고 들어옴
        notifyObservers();
    }

    @Override
    public void registerObserver(Observer observer) {
        // observer 등록
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        // observer 제거
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        // 등록된 observer 들에게 전달
        for (Observer observer : observers) {
            observer.alarm();
        }
    }
}

 

위 코드를 보면 가장 먼저 Observer 라는 인터페이스를 만들고 Table과 Store 클래스가 구현하도록 만든 것을 볼 수 있습니다. Observer 인터페이스는 오로지 이 인터페이스의 구현체가 alarm() 이라는 메서드가 있다는 것만 알려주고 있습니다.

 

Door 클래스가 구현하는 인터페이스인 Subject에는 registerObserver, removeObserver, notifyObservers 메소드가 있는데 각각 Observer 구현체를 추가하고 제거하고 observer 객체들에게 알람을 울리도록 하는 역할을 하는 메소드 입니다.

 

이제 새로운 꿀잠 포인트가 추가될 때 마다 단순시 Observer 인터페이스를 구현하고 registerObserver를 통해 등록하기만 하면 됩니다. 사장님에게 들킨 자리는 removeObserver를 통해 제거할 수 있겠죠. 

 

 

이렇게 특정 객체에 변화가 있을때 혹은 그 객체에 일어나는 일을 알려줘야 하는 다른 객체가 있을 때 쉽게 사용할 수 있는 방법이 바로 옵저버 패턴(Observer Pattern)입니다. 마치 스타크래프트에 나오는 옵저버 처럼 일어나는 일을 관찰하고 있다가 필요할 때 알려주는 역할을 하지요. 자바에서는 API를 통해 이 옵저버 패턴을 제공하고 있기도 합니다.

 

 


위 내용은 한빛미디어에서 출판된 Head First Design Patterns 중 2장의 내용을 임의대로 수정하고 요약한 것입니다.

반응형
donaricano-btn
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함