[Design Pattern] Observer Pattern

Observer Pattern

객체의 상태 변화를 다른 객체들에게 통지하고 싶을 때 사용하는 패턴

예시 상황

웹사이트가 응답 속도가 느리거나 연결이 안 되면 알림을 보내는 서비스를 구현한다.

public class StatusChecker {

    private EmailSender emailSender;
    private SmsSender smsSender;
    private Messenger messenger;

    public void check() {
        Status status = loadStatus();
    
        // 웹사이트의 상태가 비정상일 경우 이메일과 SMS 알림을 보낸다.
        if (status.isNotNormal) {
            emailSender.sendEmail(status);
            smsSender.sendSms(status);
            messenger.sendMessage(status);
        }
    }
}

옵저버 패턴 적용

옵저버 패턴에서 주제(subject)에 해당하는 클래스의 구현

주제(subject)는 두가지 책임을 갖는다.

public abstract class StatusSubject {
    
    private List<StatusObserver> observers = new ArrayList<StatusObserver>();
    
    // 옵저버를 추가한다.
    public void add(StatusObserver observer) {
        observers.add(observer);
    }    

    // 옵저버를 제거한다.
    public void remove(StatusObserver observer) {
        observers.remove(observer);
    }

    // 옵저버에게 변경 내역을 알린다.
    public void notifyStatus(Status status) {
        for (StatusObserver observer: observers) {
            observer.onAbnormalStatus(status);
        }
    }
}

옵저버에게 알림이 필요한 콘크리트 클래스의 구현

public class StatusChecker extends StatusSubject {

    public void check() {
        Status status = loadStatus();

        if (status.isNotNomal()) {
            super.notifyStatus(status);
        }
    }
}

옵저버 객체를 구현한 클래스는 주제 객체가 호출하는 메서드에서 필요한 기능을 구현하면 된다.
옵저버 인터페이스

public interface StatusObserver {
    
    void onAbnormalStatus(Status status);
}

콘크리트 옵저버 클래스

public class StatusEmailSender implements StatusObserver {

    @Override
    public void onAbnormalStatus(Status status) {
        sendEmail(status);
    }
}

StatusChecker의 사용

public class Client {
            
    public void checkStatus() {
        StatusChecker statusChecker = new StatusChecker();
        statusChecker.add(new StatusEmailSender()); // 옵저버로 등록

        // statusChecker는 상태를 체크해서 등록된 옵저버에 알림을 보낸다.
        statusChecker.check();
    }
}

Reference