- 정의
- 구현
옵저버 패턴 (Observer Pattern)
특정 객체에 상태가 변할 때(=이벤트가 발생할 때), 그와 연관된 객체들에게 알려주고 자동으로 갱신이 되도록 하는 전형적인 One-to-Many(1:N)의 디자인 패턴
Publish/Subscribe 모델이라고 불리기도 함.
가장 전형적인 예 - Youtube
Subject
(주체) = PublisherObserver
(관찰자)구조
과거에는 사용자(Observer)가 신문사(Subject)에 정기 구독을 요청하면, 신문사는 옵저버의 정보(주소 등)를 업데이트한 후, 신청한 사용자 모두에게 매일 아침 새로운 내용의 신문을 배달했다. 또한, 배달을 원치 않을 때, 사용자는 구독을 해제할 수도 있다.
Publisher => 신문사
public interface Publisher {
void add(Observer observer);
void delete(Observer observer);
void notifyObserver();
}
add
), 삭제(delete
)하거나 구독자에게 알려주는 기능(notifyObserver
)를 추가import java.util.ArrayList;
import java.util.List;
public class NewsCompany implements Publisher {
private List<Observer> observers;
private String newsTitle;
public NewsCompany(){
observers = new ArrayList<>();
}
@Override
public void add(Observer observer) {
observers.add(observer);
}
@Override
public void delete(Observer observer) {
int idx = observers.indexOf(observer);
observers.remove(idx);
}
@Override
public void notifyObserver() {
for (Observer observer : observers) {
observer.update(newsTitle);
}
}
public void setNewsTitle(String newsTitle){
this.newsTitle = newsTitle;
notifyObserver();
}
}
List<Observer> observers
를 통해 1:N
의 연관관계가 성립하고, 변경할 데이터(newsTitle
)에 대한 변수를 선언하여 메서드(setNewsTitle()
)를 통해 변경하도록 구현Observer => 신문 구독자들
public interface Observer {
void update(String contents);
}
update()
가 있다.public class First implements Observer {
private Publisher publisher;
private String contents;
public First(Publisher publisher) {
this.publisher = publisher;
publisher.add(this);
}
@Override
public void update(String contents) {
this.contents = contents;
System.out.println("변경된 신문사의 내용 (First) : " + this.contents);
}
}
////
public class Second implements Observer {
private Publisher publisher;
private String contents;
public Second(Publisher publisher) {
this.publisher = publisher;
publisher.add(this);
}
@Override
public void update(String contents) {
this.contents = contents;
System.out.println("변경된 신문사의 내용 (Second) : " + this.contents);
}
}
First
, Second
두 명의 구독자가 존재public class Main {
public static void main(String[] args) {
NewsCompany newsCompany = new NewsCompany();
First first = new First(newsCompany);
Second second = new Second(newsCompany);
newsCompany.setNewsTitle("초 대박 뉴스!!!!");
System.out.println("-----------");
newsCompany.setNewsTitle("초초초 대박 뉴스!!!!");
}
}
print: >>>
변경된 신문사의 내용 (First) : 초 대박 뉴스!!!!
변경된 신문사의 내용 (Second) : 초 대박 뉴스!!!!
-----------
변경된 신문사의 내용 (Frist) : 초초초 대박 뉴스!!!!
변경된 신문사의 내용 (Second) : 초초초 대박 뉴스!!!!
한 개의 신문사를 설립(NewsCompany newsCompany = new NewsCompany();
)
각 구독자들은 생성시점에 신문사에 구독
데이터가 변경될 때마다 알림
구독을 해제하는 경우에, 해제의 주체는 신문사가 아닌 구독자이다.
public class First implements Observer {
//...
public void unsubscribe() {
publisher.delete(this);
}
}
public class Main {
public static void main(String[] args) {
NewsCompany newsCompany = new NewsCompany();
First first = new First(newsCompany);
Second second = new Second(newsCompany);
newsCompany.setNewsTitle("초 대박 뉴스!!!!");
System.out.println("-----------");
newsCompany.setNewsTitle("초초초 대박 뉴스!!!!");
first.unsubscribe();
System.out.println("First 구독 취소 후,,,,,,,");
newsCompany.setNewsTitle("나쁜 내용의 뉴스");
}
}
print >>>
변경된 신문사의 내용 (First) : 초 대박 뉴스!!!!
변경된 신문사의 내용 (Second) : 초 대박 뉴스!!!!
-----------
변경된 신문사의 내용 (First) : 초초초 대박 뉴스!!!!
변경된 신문사의 내용 (Second) : 초초초 대박 뉴스!!!!
First 구독 취소 후,,,,,,,
변경된 신문사의 내용 (Second) : 나쁜 내용의 뉴스
결론
Subject
)는 옵저버(Observer
)가 무슨 동작을 하는지 모른다. 옵저버가 추가되거나 제거되어도 주제에 전혀 영향을 주지 않는다. = 느슨한 결합