Java 디자인 패턴-09.Observer
            
          
        
(Java 디자인 패턴 스터디 모집 중 : https://github.com/bluedskim/javaDesignPatterns)
Observer 패턴 다이어그램
(출처:https://dev.to/danlee0528/design-pattern-the-observer-pattern-3oha)
해결하려는 문제 : 알림의 주체는 누구인가?
특징/용도
- publisher-subscriber(pub-sub)이라고도 한다.
 
- 객체들은 one(publisher)-to-many(subscriber) 관계를 가진다.
 
- subscriber는 publisher알지만 publisher는 subscriber를 알지 못한다. 즉 관계는 단방향이다.
 
고려사항
- event driven아키텍처의 분산 이벤트 관리에서 많이 사용된다(https://en.wikipedia.org/wiki/Observer_pattern)
 
- 동시성 처리를 위해 observer가 subject-events를 수신할 때 멀티쓰레드로 동작할 필요도 있다.
 
클래스 다이어그램

소스
- PropertyChangeSupport 를 사용한 observer 패턴 샘플
 
- observable(Subject, Publisher) : NewsAgency.java
 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
  | 
package net.dskim.desingpattern.observer;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
/**
 * Subject(Publisher)
 */
public class NewsAgency {
	private String previousNews;
	private PropertyChangeSupport support;
	public NewsAgency() {
		support = new PropertyChangeSupport(this);
	}
	public void addPropertyChangeListener(PropertyChangeListener pcl) {
		support.addPropertyChangeListener(pcl);
	}
	public void removePropertyChangeListener(PropertyChangeListener pcl) {
		support.removePropertyChangeListener(pcl);
	}
	public void setNews(String news) {
		support.firePropertyChange("news", this.previousNews, news);
		this.previousNews = news;
	}
}
  | 
 
 
- observer(Listener, Subscriber) : NewsChannel.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
  | 
package net.dskim.desingpattern.observer;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
/**
 * Listener(Subscriber)
 */
public class NewsChannel implements PropertyChangeListener {
	private String news;
	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		news = (String) evt.getNewValue();
	}
	public String getNews() {
		return news;
	}
}
  | 
 
 
- client : ObserverTest.java
 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
  | 
package net.dskim.desingpattern.observer;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ObserverTest {
	@Test
	public void whenChangingPCLNewsAgencyState_thenONewsChannelNotified() {
		String newsName = "뉴스 제목";
		NewsAgency observable = new NewsAgency();
		NewsChannel observer1 = new NewsChannel();
		NewsChannel observer2 = new NewsChannel();
		observable.addPropertyChangeListener(observer1);
		observable.addPropertyChangeListener(observer2);
		observable.setNews(newsName);
		log.info("observer.getNews()={}", observer1.getNews());
		assertEquals(observer1.getNews(), newsName);
		assertEquals(observer2.getNews(), newsName);
	}
}
  | 
 
 
참고