인턴활동을 하며 실 업무에 들어가기 위해 기존 코드를 학습하는 과정 중에 있다. 기존 코드를 학습하기 위해 기존 코드에 사용되어있는 디자인 패턴을 학습하려고 한다. 오늘은 옵저버 패턴이 사용된 부분을 이해하기 위해 Oberver Pattern을 학습해보았다.
Oberver Pattern
옵저버 패턴(Observer Pattern) : 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고, 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의
옵저버 패턴(Observer Pattern)은 객체 간의 일대다(One-to-Many) 의존 관계를 정의하는 디자인 패턴입니다. 한 객체의 상태가 변경되면, 그 상태에 의존하는 다른 객체들(옵저버)에게 자동으로 통지되고, 그 결과 이들 객체의 상태도 자동으로 갱신됩니다. 주로 이벤트 기반 시스템에서 많이 사용됩니다.
간단한 예로, 아파트 중개를 생각해볼 수 있습니다. 사용자가 특정 아파트에 관심이 있을 때, 매번 방이 있는지 없는지를 확인하기 위해 지속적으로 중개업체에 연락을 해야 한다면 비효율적일 것입니다. 대신, 옵저버 패턴을 적용하면, 사용자는 한 번만 관심 아파트를 등록해두면 중개업체(주제 객체)가 방이 생길 때 알아서 연락을 해줍니다.
옵저버 패턴 적용 전 )
옵저버 패턴 적용 후 )
옵저버 패턴의 구조는 크게 두 가지 주요 인터페이스로 나뉩니다: 주제(Subject) 와 옵저버(Observer).
Subject
인터페이스는 옵저버를 등록, 제거하고 상태 변경 시 옵저버에게 알리는 역할을 담당합니다. 주제는 상태가 변경될 때마다 옵저버에게 상태 변경 사실을 통지합니다.
interface Subject {
void registerObserver(Observer o); // 옵저버 등록
void removeObserver(Observer o); // 옵저버 삭제
void notifyObservers(); // 옵저버에게 업데이트 알림
}
class SubjectImpl implements Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
public String getState() {
return state;
}
public void setState(String newState) {
this.state = newState;
notifyObservers(); // 상태 변경 시 옵저버들에게 알림
}
}
registerObserver()
: 옵저버를 리스트에 등록합니다.removeObserver()
: 리스트에서 옵저버를 제거합니다.notifyObservers()
: 상태가 변경되면 등록된 모든 옵저버에게 알림을 보냅니다.Observer
인터페이스는 주제의 상태가 변경되었을 때 이를 감지하고 자신의 상태를 업데이트하는 메소드를 포함합니다. 옵저버는 주제의 상태 변화에 따라 필요한 행동을 정의할 수 있습니다.
interface Observer {
void update(String newState); // 주제의 상태가 변경되었을 때 호출됨
}
class ObserverImpl implements Observer {
private String observerState;
@Override
public void update(String newState) {
this.observerState = newState;
display();
}
public void display() {
System.out.println("옵저버 상태가 업데이트 되었습니다: " + observerState);
}
}
update()
: 주제로부터 새로운 상태를 전달받아 자신의 상태를 갱신합니다.옵저버 패턴은 날씨 모니터링 시스템과 같은 실시간 정보 전달 시스템에서 많이 사용됩니다. 날씨 센서(주제)가 온도, 습도 등의 정보를 업데이트하면, 이를 구독한 디스플레이 장치(옵저버)가 상태를 자동으로 갱신합니다.
class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
public WeatherData() {
observers = new ArrayList<>();
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity) {
this.temperature = temperature;
this.humidity = humidity;
measurementsChanged();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity);
}
}
}
class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
@Override
public void update(float temperature, float humidity) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("현재 상태: 온도 " + temperature + "도, 습도 " + humidity + "%");
}
}
이 예제에서는 WeatherData
객체가 주제 역할을 하고, CurrentConditionsDisplay
객체가 옵저버 역할을 합니다. 날씨 데이터가 갱신되면, 자동으로 옵저버들에게 알림을 보내고 상태가 업데이트됩니다.
옵저버 패턴은 이벤트 기반 시스템이나 실시간 데이터 전달이 필요한 시스템에서 매우 유용한 디자인 패턴입니다. 여러 객체가 동일한 주제의 상태에 의존해야 하거나, 상태 변경을 알림받아야 할 때 유용합니다. 느슨한 결합과 유연성을 제공하는 반면, 사용 범위에 따라 성능 저하나 복잡성을 초래할 수 있으므로 적절한 상황에 맞게 적용하는 것이 중요합니다.
멋있어여