[Design Pattern] Observer pattern, 옵저버 패턴
옵저버 패턴은 객체의 상태 변화를 관찰하는 관찰자(옵저버)들의 목록을 객체에 등록하여 상태 변화가 있을 떄마다 메서드를 통해 목록의 옵저버에게 통지하는 디자인 패턴이다. - Wikipedia
옵저버 패턴은 객체의 상태변화를 감지하는 옵저버가 객체의 상태변화가 있을 때 그와 연관된 객체들에게 알림을 보내는 디자인 패턴으로 행위 패턴에 포함됩니다.
- Subject는 Observer를 등록, 해제와 변경이 있을 경우 Observer에게 알리는 기능을 합니다.
- Observer는 updating interface를 가지고 있으며 Subject에서 변화가 있을 때 알림을 수신합니다. 모든 observers는 Observer 인터페이스를 implements해야하며 Subject가 알림을 보낼 때 작동하는 update() 메소드를 가지고 있습니다.
- ConcreteSubject는 Subject 인터페이스를 implements 하며, 상태 변화가 발생했을 때 notifyObservers() 메소드를 사용하여 연결되어있는 observers에게 변경을 알립니다.
- ConcreteObservers는 Observer 인터페이스를 implements 하며 각각의 observer는 concrete subject에 등록 및 해제합니다.
예시를 통해 살펴보도록 하겠습니다.
예시 출처 - JAVA DESIGN PATTERNS : reusable solution to common problems (Java Code Geeks)
위의 예시는 ConcreteSubject인 CommentaryObject가 Subject와 Commentary를 implements하고, ConcreteObserver인 SMSUsers가 Observer를 implements 하는 예제입니다.
CommentaryObject는 실시간으로 스포츠 뉴스를 SMSUsers에게 전달하며, SMSUsers는 이 스포츠 뉴스를 구독하는 구독자 입니다.
우선 Subject부터 구현하도록 하겠습니다.
- Subject interface
public interface Subject {
public void subscribeObserver(Observer observer);
public void unSubscribeObserver(Observer observer);
public void notifyObservers();
public String subjectDetails();
}
Subject 인터페이스는 위에서 말씀드린 것처럼 구독자를 등록 및 해제, 상태 변화 발생 시 알림의 세 가지를 수행해야 합니다.
subscribeObserver(Observer observer) 메소드는 observer를 등록 합니다.
unSubscribeObserver(Observer observer) 메소드는 observer를 해제 합니다.
notifyObservers() 메소드는 변화가 발생하면 옵저버에게 알리는 역할을 합니다.
다음으로 Observer입니다
- Observer interface
public interface Observer {
public void update(String desc);
public void subscribe();
public void unSubscribe();
}
update(String desc) 메소드는 observer가 등록되어있는 subject에 변경이 생겼을 때, 변경을 알리기 위해 호출됩니다.
subscribe() 메소드는 자신을 subject에 등록할 때 사용됩니다.
unSubscribe() 메소드는 등록된 subject에서 등록 해제할 때 사용됩니다.
- Commentary interface
public interface Commentary {
public void setDesc(String desc);
}
위의 interface는 스포츠 경기의 실시간 상황을 commentary object에 업데이트 하는데 사용됩니다. interface principle을 준수하기 위해 위처럼 사용합니다. (단일 책임 원칙)
- CommentaryObject
import java.util.List;
public class CommentaryObject implements Subject,Commentary{
private final List<Observer>observers;
private String desc;
private final String subjectDetails;
public CommentaryObject(List<Observer>observers,String subjectDetails){
this.observers = observers;
this.subjectDetails = subjectDetails;
}
@Override
public void subscribeObserver(Observer observer) {
observers.add(observer);
}
@Override
public void unSubscribeObserver(Observer observer) {
int index = observers.indexOf(observer);
observers.remove(index);
}
@Override
public void notifyObservers() {
System.out.println();
for(Observer observer : observers){
observer.update(desc);
}
}
@Override
public void setDesc(String desc) {
this.desc = desc;
notifyObservers();
}
@Override
public String subjectDetails() {
return subjectDetails;
}
}
위의 CommentaryObject는 Commentary와 Subject를 implements하는 ConcreteSubject입니다.
observers를 List형태로 저장합니다.
- SMSUsers
public class SMSUsers implements Observer{
private final Subject subject;
private String desc;
private String userInfo;
public SMSUsers(Subject subject,String userInfo){
if(subject==null){
throw new IllegalArgumentException("No Publisher found.");
}
this.subject = subject;
this.userInfo = userInfo;
}
@Override
public void update(String desc) {
this.desc = desc;
display();
}
private void display(){
System.out.println("["+userInfo+"]: "+desc);
}
@Override
public void subscribe() {
System.out.println("Subscribing "+userInfo+" to "+subject.subjectDetails()+ ←-
" ...");
this.subject.subscribeObserver(this);
System.out.println("Subscribed successfully.");
}
@Override
public void unSubscribe() {
System.out.println("Unsubscribing "+userInfo+" to "+subject.subjectDetails ←-
()+" ...");
this.subject.unSubscribeObserver(this);
System.out.println("Unsubscribed successfully.");
}
}
위의 코드는 Observer를 implements하는 SMSUsers 코드입니다.
ConcreteObserver에 해당합니다.
'[컴퓨터공학] > [Design Pattern]' 카테고리의 다른 글
[Design Pattern] 데코레이터 패턴 - Decorator Pattern (1) | 2022.10.08 |
---|---|
[Design Pattern] 옵저버 패턴 - Python (1) | 2022.09.22 |