도찐개찐
[코드디자인패턴-JAVA] Observer Pattern 본문
Observer Pattern
사용시점
- 상태 의존성: 하나의 객체의 상태 변경이 다른 객체의 상태나 동작에 영향을 미칠 때
- 이벤트 발생: 특정 이벤트가 발생했을 때 관찰자들에게 알림을 보낼 필요가 있을 때
- 코드 결합 최소화: 주제와 관찰자 사이의 결합을 최소화 하고자 할때
종류
- 푸시 모델: 주제가 관찰자에게 필요한 모든 정보를 직접 보내는 방식, 관찰자는 주제로부터 푸시된 정보만을 이용합니다.
- 풀 모델: 주제가 변화를 통보만 하고, 관찰자는 필요한 정보를 주제로부터 직접 가져오는 방식입니다. 이 경우 관찰자가 필요한 정보만을 가져올 수 있으며, 주제와 관찰자 사이의 의존성이 낮아 집니다.
결론
- 상태 변화를 관찰하는 객체들에게 상태 변화를 알려주는 패턴
- 주로 이벤트 핸들링 시스템에서 사용되며, 하나의 주제(Subject) 객체와 그 주제를 관찰하는 관찰자(Observer) 객체들로 구성.
Push Model(푸시모델)
1. Observer 인터페이스: 관찰자 정의
public interface Observer {
void update(String message);
}
2. Subject 클래스: 주제를 정의 하고, 관찰자를 등록하거나 제거 합니다.
import java.util.ArrayList;
import java.util.List;
public class Subject {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
3. ConcreteObser클래스: 실제 관찰자 구현
public class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " received message: " + message);
}
}
public class Main {
public static void main(String[] args) {
Subject subject = new Subject();
Observer observer1 = new ConcreteObserver("Observer1");
Observer observer2 = new ConcreteObserver("Observer2");
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notifyObservers("Hello, Observers!");
}
}
Main.main(null);
Observer1 received message: Hello, Observers!
Observer2 received message: Hello, Observers!
장점
- 확장성: 새로운 관찰자를 추가하거나 제거하기 쉽습니다.
- 낮은 결합도: 주제와 관찰자 사이의 결합도가 낮아, 하나를 변경해도 다른 하나에 영향을 미치지 않습니다.
단점
- 메모리와 성능 문제: 많은 수의 관찰자가 있는 경우, 모든 관찰자에게 알림을 보내는데 비용이 발생 할 수 있습니다.
- 데이터의 일관성: 관찰자들이 동일한 데이터를 기반으로 작업한다고 보장할 수 없으므로, 데이터 일관성을 유지하는 것이 복잡 할 수 있습니다.
Pull Model(풀모델)
1. Subject 클래스: 관찰의 대상이 되는 클래스로, 상태가 변경 되면 등록 된 Observer들에게 알림
import java.util.ArrayList;
import java.util.List;
public class Subject {
private List<Observer> observers = new ArrayList<>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer) {
observers.add(observer);
}
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
2. Observer 추상 클래스: 관찰자들이 구현해야 할 추상 클래스로, Subject의 상태 변경을 알리는 메소드가 정의
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
3. ConcreteObserver 클래스: Observer 추상 클래스를 구현한 구체 클래스로, 상태 변경을 알리면 해당 정보를 출력
public class ConcreteObserver extends Observer {
public ConcreteObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("State has been updated to " + subject.getState());
}
}
public class Main {
public static void main(String[] args) {
Subject subject = new Subject();
new ConcreteObserver(subject);
subject.setState(10);
}
}
Main.main(null);
State has been updated to 10
장점
- 데이터의 효율성: 관찰자가 필요한 데이터만 주제로부터 가져오므로 불필요한 데이터 전송이 없음
- 유연성: 관찰자가 자신이 필요한 데이터를 직접 선택해 가져올 수 있으므로 패턴 유연성 증가
단점
- 성능 이슈: 관찰자가 주제로부터 데이터를 가져오는 과정에서 추가 메서드 호출이 필요하므로 성능에 영향 미칠 가능성 있습니다.
- 복잡성 증가: 풀 모델에서는 주제와 관찰자 간의 상호작용이 더 복잡해지므로 설계와 유지보수가 어려울 수 있습니다.
대표 사례
- Swing: 자바의 GUI 라이브러리인 Swing에서는 사용자 인터페이스의 이벤트 처리에 Observer 패턴을 사용합니다. 이벤트 리스너가 특정 이벤트에 응답하여 액션을 수행하게 됩니다.
- JavaBeans: JavaBeans에서는 속성 변경 리스너를 통해 Observer 패턴을 구현합니다. 프로퍼티의 변경을 감지하고 이를 관찰하는 객체에게 알림을 보냅니다.
- RxJava: RxJava는 자바에서 리액티브 프로그래밍을 지원하는 라이브러리로, Observer 패턴의 확장된 형태를 제공합니다. Observable이 이벤트를 생성하고 Observer가 이를 구독하며 반응합니다.
- Spring Framework: Spring에서는 이벤트 처리 메커니즘에 Observer 패턴을 사용합니다. 이벤트 발생 시 등록된 리스너가 알림을 받고 처리하게 됩니다.
- Apache ZooKeeper: 분산 코디네이션 서비스를 제공하는 ZooKeeper도 Observer 패턴을 사용합니다. 클라이언트는 ZooKeeper의 노드에 watch를 걸고 변화를 감지하면 알림을 받습니다.
728x90
'프로그래밍 > 코드디자인패턴' 카테고리의 다른 글
[코드디자인패턴-JAVA] Facade Pattern (0) | 2024.02.29 |
---|---|
[코드디자인패턴-JAVA] Factory Method Pattern (0) | 2024.02.29 |
[코드디자인패턴-JAVA] Singleton Pattern (0) | 2024.02.29 |
[코드디자인패턴-JAVA] State Pattern (0) | 2024.02.29 |
[코드디자인패턴-JAVA] Strategy Pattern (0) | 2024.02.29 |
Comments