1. 옵저버 패턴 (Observer pattern)
- 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록해 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴
- 주로 분산 이벤트 핸들링 시스템을 구현하는데 사용된다.
- 주체 객체 + 상태의 변경을 알아야 하는 관찰 객체가 존재하며 1:1 또는 1:N의 관계가 될 수 있다.
- Subject : 이벤트를 발생시키는 주체, 관찰 대상 객체
- Observer : 이벤트를 관찰하는 대상, 이벤트가 발생하면 콜백을 받아 notify 함수를 통해 Subject가 발행한 메시지 이외에도, 옵서버 자신이 생성한 인자값을 하위 Observer에게 전달
- ConcreateObserver : notify 함수를 통해 이벤트가 발생했을 때 처리할 각자의 동작을 정의
1-1. 옵저버 패턴의 장점 [2]
- 실시간으로 한 객체의 변경사항을 다른 객체에 전파할 수 있다.
- 느슨한 결함으로 시스템이 유연하고 객체 간의 의존성을 제거할 수 있다.
1-2. 옵저버 패턴의 단점 [2]
- 너무 많이 사용하게 되면 상태 관리가 힘들 수 있다.
- 데이터 배분에 문제가 생기면 자칫 큰 문제로 이어질 수 있다. [2]
1-3. 옵저버 패턴의 구현 (JAVA) [1]
(1) Java에서는 기본으로 제공하는 Observable 클래스와 Observer 인터페이스를 이용하여 좀 더 쉽게 구현 가능
*하지만 Observable 객체는 JAVA 9부터 Deprecated 되었음*
EventSouce.java
package obs;
import java.util.Observable; // 이 부분이 옵저버에게 신호를 보내는 주체입니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class EventSource extends Observable implements Runnable
{
public void run()
{
try
{
final InputStreamReader isr = new InputStreamReader( System.in );
final BufferedReader br = new BufferedReader( isr );
while( true )
{
final String response = br.readLine();
setChanged();
notifyObservers( response );
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
ResoponseHandler.java
package obs;
import java.util.Observable;
import java.util.Observer; /* 여기가 옵저버 */
public class ResponseHandler implements Observer
{
private String resp;
public void update (Observable obj, Object arg)
{
if (arg instanceof String)
{
resp = (String) arg;
System.out.println("\nReceived Response: "+ resp );
}
}
}
myApp.java
/* 여기서부터가 프로그램 시작점 */
package obs;
public class MyApp
{
public static void main(String args[])
{
System.out.println("Enter Text >");
// 이벤트 발행 주체를 생성함 - stdin으로부터 문자열을 입력받음
final EventSource evSrc = new EventSource();
// 옵저버를 생성함
final ResponseHandler respHandler = new ResponseHandler();
// 옵저버가 발행 주체가 발행하는 이벤트를 구독하게 함
evSrc.addObserver( respHandler );
// 이벤트를 발행시키는 쓰레드 시작
Thread thread = new Thread(evSrc);
thread.start();
}
}
* Observable [3]
- setChanged() : 객체가 변경된 것을 표시하는 메서드
- notifyObservers() : 객체가 변경된 경우 모든 Observer에게 알리는 메서드
- addObserver() : 객체에 Observer 추가
*Observer [4]
- update() : 객체가 변경될 때 호출되는 메서드
(2) 리스너 사용 [5]
Subject
public interface Subject {
public void registerObserver(Observer observer); //Observer 등록
public void unregisterObserver(Observer observer); //Observer 해제
public void notifyObservers(String msg); //이벤트 발생 시 Observers들에게 알려주기
}
import java.util.ArrayList;
import java.util.List;
public class YouTuber implements Subject {
private List<Observer> subscriberList; //Observers를 관리할 List
public YouTuber() {
subscriberList = new ArrayList<>();
}
//Subject 인터페이스의 기능들 구현
@Override
public void registerObserver(Observer observer) {
subscriberList.add(observer);
}
@Override
public void unregisterObserver(Observer observer) {
subscriberList.remove(observer);
}
@Override
public void notifyObservers(String msg) {
for (Observer observer : subscriberList) {
observer.notifySubscriber(msg);
}
}
}
Observer
public interface Observer {
public void notifySubscriber(String msg);
}
public class SubscriberA implements Observer {
@Override
public void notifySubscriber(String msg) {
System.out.println(this.getClass() + " : " + msg);
}
}
public class SubscriberB implements Observer {
@Override
public void notifySubscriber(String msg) {
System.out.println(this.getClass() + " : " + msg);
}
}
Main
public class Main {
public static void main(String[] args) {
YouTuber youTuber = new YouTuber();
Observer subscriberA = new SubscriberA();
Observer subscriberB = new SubscriberB();
System.out.println("subscriberA 구독 등록");
youTuber.registerObserver(subscriberA);
System.out.println("subscriberB 구독 등록");
youTuber.registerObserver(subscriberB);
youTuber.notifyObservers("New Video Upload!");
}
}
참고자료
[1] 옵서버 패턴 : https://ko.wikipedia.org/wiki/%EC%98%B5%EC%84%9C%EB%B2%84_%ED%8C%A8%ED%84%B4
[2] [Design Pattern] 옵저버 패턴(Ovserver Pattern)에 대하여 : https://coding-factory.tistory.com/710
[3] Observable (Java Platform SE 7) : https://docs.oracle.com/javase/7/docs/api/java/util/Observable.html
[4] Observer (Java Platform SE 7) : https://docs.oracle.com/javase/7/docs/api/java/util/Observer.html
[5] 옵저버 패턴(Observer Pattern) : https://sorjfkrh5078.tistory.com/140
'Language > JAVA' 카테고리의 다른 글
[Java] Enum (0) | 2024.01.29 |
---|---|
[JAVA] 싱글톤 패턴 (Singleton pattern) (0) | 2022.12.04 |