본문 바로가기
Languages/디자인패턴

[Java] 옵저버(Observer) 패턴

by yoon_seon 2023. 6. 12.

Observer 패턴이란?

옵서버 패턴은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. 주로 분산 이벤트 핸들링 시스템을 구현하는 데 사용된다. 

즉, 객체의 상태가 변할 경우 연관된 객체들에게 알린다 라는 의미의 패턴으로, 실생활에 비유하자면 구독을 예시로 들 수 있을 것 같다.

 

Observer 패턴 예시

구독자들이 유튜버의 새로운 소식에 대한 알림을 받는다 라는 주제로 예시를 들어보았다.

 

Youtuber 인터페이스

public interface Youtuber {
    void addSubscriber(Subscriber subscriber);
    void removeSubscriber(Subscriber subscriber);
    void upload(String title);
}
  • 구독자 추가, 구독자 삭제, 업로드의 역할을 정의하였다.

 

Subscriber 추상메서드

public abstract class Subscriber {
    public void follow(Youtuber youtuber) {
        youtuber.addSubscriber(this);
    };

    public void unFollow(Youtuber youtuber) {
        youtuber.removeSubscriber(this);
    };

    public void alert(String msg) {
        System.out.println("알림 : " + msg);
    };
}
  • 구독자는 유튜버를 팔로우할 수 있으며 자신을 구독자 리스트에 추가할 수 있다.
  • 구독자는 유튜버를 언팔로우할 수 있으며 자신을 구독자 리스트에서 삭제할 수 있다.
  • 구독자는 알림을 받을 수 있다.

 

Youtuber를 구현한 쯔양 클래스

public class Tzuyoung implements Youtuber {
    private List<Subscriber> subscribers = new ArrayList<>();

    @Override
    public void addSubscriber(Subscriber subscriber) {
        subscribers.add(subscriber);
    }

    @Override
    public void removeSubscriber(Subscriber subscriber) {
        subscribers.remove(subscriber);
    }

    @Override
    public void upload(String title) {
        subscribers.forEach(subscriber -> subscriber.alert("쯔양님의 새로운 소식이 있습니다. [" + title + "]"));
    }
}
  • 쯔양(유튜버)는 Subscriber(구독자)들의 리스트를 가지고 있다.
  • 리스트에 구독자를 추가, 삭제할 수 있다.
  • upload 메서드를 보면 유튜버가 새로운 소식을 업로드할 때 구독자들에게 알림을 보낸다.
    Youtuber의 upload 메서드 호출 시 Subscriber의 alert()를 호출한다.

 

Subscriber를 확장한 Lee, Kim, Pack 클래스

public class Lee extends Subscriber {
    @Override
    public void alert(String msg) {
        System.out.println("Lee 알림 : " + msg);
    }
}
public class Kim extends Subscriber {
    @Override
    public void alert(String msg) {
        System.out.println("Kim 알림 : " + msg);
    }
}
public class Pack extends Subscriber {
    @Override
    public void alert(String msg) {
        System.out.println("Pack 알림 : " + msg);
    }
}
  • 받은 알림을 출력한다.

 

예제 실행 Main 메서드

public static void main(String[] args) {
    public static void observerExample() {
        Tzuyoung tzuyoung = new Tzuyoung();

        Kim kim = new Kim();
        Lee lee = new Lee();
        Pack pack = new Pack();

        kim.follow(tzuyoung);
        lee.follow(tzuyoung);
        pack.follow(tzuyoung);

        tzuyoung.upload("첫 번째 동영상");

        kim.unFollow(tzuyoung);

        tzuyoung.upload("두 번째 동영상");

    }
}
  1. 구독자 kim, lee, pack은 유튜버 tzuyoung을 팔로우 한다.
  2. tzuyoung 유튜버가 소식을 업로드한다.
  3. 구독자 kim이 유튜버 tzuyoung을 언팔로우한다.

 

실행 결과

  • tzuyoung 유튜버가 두 번째 소식을 업로드 할 때 구독을 취소한 kim은 알림 대상에서 제외되어 알림을 받지 않는 것을 확인할 수 있다.

 

이 처럼 객체의 상태가 변화될 때 연관된 객체들에게 알림을 보낼 수 있게 되었다. 이것이 옵저버 패턴이다.

코드를 자세히 보면 객체 간의 결합도가 낮은 것을 확인할 수 있으며 한 객체의 상태 변화가 다른 객체들에게 영향을 주지 않으면서 상호작용할 수 있는 유연한 구조를 구현할 수 있어서 시스템의 확장성과 유지보수성을 향상시킬 수 있다.

댓글