[디자인 패턴] Observer pattern

do_large·2022년 1월 9일
1

패턴

목록 보기
2/2

  • 옵저버 패턴(observer pattern)은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다.
  • 이 패턴의 핵심은 옵저버 또는 리스너(listener)라 불리는 하나 이상의 객체를 관찰 대상이 되는 객체(Subject)에 등록시킨다. 그리고 각각의 옵저버들은 관찰 대상인 객체가 발생시키는 이벤트를 받아 처리한다.
  • 1대다관계가 형성된다.

  • Subject: Observer 를 알고 있는 주체입니다. 이는 Observer 를 등록하고 제거하는 데 필요한 인터페이스를 정의합니다.
  • Observer: Subject 에서 변화했다고 알렸을때 갱신해야하는데 필요한 인터페이스를 정의합니다.
  • ConcreteSubject: 객체에게 (Observer 들에게) 알려줘야할 상태를 저장하고, notify 해야할 함수를 만들도록 합니다.
  • ConcreteObserver: noti 를 받았을때 행동할 로직을 작성합니다.

각각의 파생 옵서버는 notify 함수를 구현함으로써 이벤트가 발생했을 때 처리할 각자의 동작을 정의해야 한다.

주체에는 일반적으로 등록(register), 제거(unregister) 메서드가 있는데, 전자는 새로운 옵저버를 목록에 등록하고 후자는 목록에서 옵저버를 뺀다.

  • 옵저버 패턴은 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들에게 연락이 가고 자동으로 정보가 갱신되는 1:N 의 관계를 정의한다.
  • 연결은 인터페이스를 이용하여 느슨한 결합성을 유지한다. 주체, 옵저버 인터페이스를 적용한다.

옵저버 패턴을 구현한 예시를 보자.

1. Observer interface

public interface Observer {
	public void update(String title, String news); 
}

위 인터페이스는 모든 옵저버들이 상속하는 인터페이스이다.
update라는 메서드를 오버라이드해야한다.
그래야 subject에서 state가 변경되었을때 옵저버에게 알려주기위해 update메서드를 호출해야하기때문이다.

2. Subject interface

public interface Publisher {
    public void add(Observer observer); 
    public void delete(Observer observer); 
    public void notifyObserver(); 
}

위 인터페이스는 subject의 인터페이스이다.
add, delete메서드는 observer들을 등록/제거하기위해서 사용되고,
notifyObserver메서드는 프로퍼티 변경 시 옵저버들에게 알려주기위한 메서드이다.

3. Subject 구현클래스

public class NewsMachine implements Publisher {
    private ArrayList<Observer> observers; 
    private String title; private String news; 
    
    public NewsMachine() {
    	observers = new ArrayList<>(); 
    } 
    
    @Override 
    public void add(Observer observer) { 
    	observers.add(observer);
    } 
    
    @Override
    public void delete(Observer observer) {
    	int index = observers.indexOf(observer); 
        observers.remove(index); 
    }
    
    @Override 
    public void notifyObserver() {
    	for(Observer observer : observers) { 
            observer.update(title, news); 
        } 
    } 
        
    public void setNewsInfo(String title, String news) { 
    	this.title = title;
        this.news = news; 
        notifyObserver(); 
    } 
    
    public String getTitle() {
    	return title; 
    }
    
    public String getNews() {
    	return news; 
    }
}

옵저버들을 관리하는 observers라는 배열을 가지고,
subject의 값이 변경될때 setNewsInfo라는 메서드를 호출해서 notifyObserver를 실행시킨다.

그래서 observer들의 update메서드를 실행시켜 변경된 상태를 알려준다.

4. Observer 구현 클래스

public class AnnualSubscriber implements Observer {
    private String newsString;
    private Publisher publisher;
    
    public AnnualSubscriber(Publisher publisher) { 
    	this.publisher = publisher; 
    	publisher.add(this);
    } 
    
    @Override
    public void update(String title, String news) { 
    	this.newsString = title + " \n -------- \n " + news; 
        display(); 
    }
        
    private void display() {
    	System.out.println("\n\n오늘의 뉴스\n============================\n\n" + newsString); 
    }
 }

실제 observer클래스를 보면 update메서드를 오버라이드한것을 볼수있다.
subject가 실제로 호출하는 메서드이다.

5. client

public class MainClass {
	public static void main(String[] args) {
	    	NewsMachine newsMachine = new NewsMachine();
	        AnnualSubscriber as = new AnnualSubscriber(newsMachine);
            
        	newsMachine.setNewsInfo("오늘 한파", "전국 영하 18도 입니다.");
        } 
}

0개의 댓글