옵저버 패턴 (Observer Pattern)

salbyul·2023년 1월 25일
0

Design Pattern

목록 보기
2/3
post-thumbnail

옵저버 패턴

한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고
자동으로 내용이 갱신되는 방식으로 일대다(One-To-Many) 의존성을 정의합니다.

개요

옵저버 패턴에서는 크게 두 가지를 구현해야 한다.
하나는 상태를 가지고 있는 주제(Subject),
그리고 다른 하나는 그 주제에게서 상태를 전달받는 옵저버(Observer)가 있다.

흐름은 이렇다.

주제의 상태에 변화가 있음 -> 주제에게 등록되어 있는 옵저버들에게 변화된 상태가 전달됨

코드로 바로 알아보도록 하자.

구현

먼저 상황을 가정해 보자.
우리는 군대 암구호 전달 시스템을 개발해야 한다.

public interface Subject {
	// 옵저버 등록 메서드
	public void registerObserver(Observer o);
    // 옵저버 제거 메서드
    public void removeObserver(Observer o);
    // 상태의 변화가 있을 시 호출될 메서드
    public void notifyObservers();
}

public interface Observer {
	public void update();
}

여기 주제 인터페이스와 옵저버 인터페이스가 있다.

public class Army implements Subject {

	// 등록된 옵저버들의 리스트
	private List<Observer> observers;
    // 문어
    private String challenge;
    // 답어
    private String countersign;

	public Army() {
    	observers = new ArrayList<Observer>();
    }

	// 옵저버 등록
	public void registerObserver(Observer o) {
    	observers.add(o);
    }
    
    // 옵저버 제거
    public void removeObserver(Observer o) {
    	observers.remove(o);
    }
    
    public void notifyObservers() {
    	for (Observer observer : observers) {
        	observer.update();
        }
    }
    
    // 암구호 변경 시 실행될 메서드
    public void passwordChanged() {
    	notifyObservsers();
    }
    
    // 암구호 변경 메서드
    public void setPassword(String challenge, String countersign) {
    	this.challenge = challenge;
        this.countersign = countersign;
        passwordChanged();
    }
}

위에 주제 인터페이스를 구현한 Army 클래스가 있다.
Army 클래스는 암구호가 변경되면 옵저버들에게 바로 암구호를 전달하도록 한다.

public class P96K implements Observer {

	// 문어
	private String challenge;
    // 답어
    private String countersign;
    private Army army;
    
    // 생성 시 주제에 바로 등록이 된다.
    public P96K(Army army) {
    	this.army = army;
        army.registerObserver(this);
    }
    
    // 주제의 상태 변화가 있을 시 실행될 메서드
    public void update() {
    	this.challenge = army.getChallenge;
    	this.countersign = army.getCountersign;
    }
}

옵저버 인터페이스를 구현한 P96K 클래스가 있다.
P96K 클래스는 객체로 생성될 때 Army 클래스에 옵저버로서 등록이 된다.

그리고 Army 의 암구호가 변경이 있을 시 바로 전달을 받을 수 있다.
이렇게 옵저버 패턴을 사용하게 되면 어떤 주제의 상태에 변화가 있으면, 그 주제에 등록된 옵저버들은 자동으로 변경된 값을 전달받고 사용할 수 있게 된다.

P96K 클래스의 update() 메서드를 보자.

public void update() {
	this.challenge = army.getChallenge;
	this.countersign = army.getCountersign;
    }

주제에서 값을 전달받는 것이 아니라, 값을 요청하고 있다.
이처럼 설계를 하게 되면 나중에 필요한 값만 골라서 받을 수 있는 이점이 있다.

옵저버 패턴의 예시

실제로 옵저버 패턴은 많이 사용되고 있다.
대표적으로 자바의 GUI 프레임워크인 스윙에서 사용되고 있다.

그 외에도

  • RxJava
  • 자바빈
  • RMI
  • 자바스크립트의 이벤트
  • 코코아, 스위프트

에서 사용되고 있다.

profile
꿈틀꿈틀

0개의 댓글