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);
}
}
|
참고