Observer Pattern
개요
- 옵저버 또는 리스너라 불리는 하나 이상의 객체를 관찰 대상이 되는 객체에 등록
-> 관찰 대상 객체가 발생시키는 이벤트를 받아 처리 - 이벤트가 발생하면 각 옵저버는 Callback을 받음
- 활용사례
> 이벤트 기반 프로그래밍
코드 구현
import java.util.ArrayList;
public class main {
public static void main(String[] args) {
Subject center = new Subject();
Observer ob1 = new ObserverA(); // [1]
Observer ob2 = new ObserverB();
center.registerObservers(ob1); // [2]
center.registerObservers(ob2);
center.pushButton();
}
}
class Subject {
ArrayList<Observer> obs = new ArrayList<Observer>(); // [3]
public void registerObservers(Observer ob) {
this.obs.add(ob);
}
public void unregisterObservers(Observer ob) {
this.obs.remove(ob);
}
public void notifyObservers() { // [4]
for (int i = 0; i < obs.size(); i++) {
obs.get(i).notifyO();
}
}
public void pushButton() {
System.out.println("User button is pressed!!");
notifyObservers();
}
}
interface Observer {
void notifyO();
}
class ObserverA implements Observer {
@Override
public void notifyO() {
System.out.println("- ObserverA is up!!");
}
}
class ObserverB implements Observer {
@Override
public void notifyO() {
System.out.println("- ObserverB is up!!");
}
}
- [1] Observer 생성
- [2] Observer 등록
- [3] Subject에서 Observer 등록시 Object를 저장하게 될 Array list
- [4] Subject에서 이벤트 발생 시 등록된 전체 Object에 대해서 notify 전달
코드 구현 - (응용)
- 유투브에서 구독하는 경우
> 유투버가 구독자를 선택하는 경우 (위의 일반적인 패턴)
> 구독자가 유투버를 선택하는 경우 (여기서 구현)
유투버가 구독자를 선택하는 경우 (일반적으로 그렇지 않음)
import java.util.ArrayList;
public class main {
public static void main(String[] args) {
Youtuber host = new Youtuber();
Observer ob1 = new ObserverA();
Observer ob2 = new ObserverB();
// 유투버가 구독자를 선택
//host.subsribe(ob1);
//host.subsribe(ob2);
// 구독자가 유투버 선택
ob1.subscribe(host);
ob1.subscribe(host);
host.upload();
}
}
class Youtuber {
private ArrayList<Observer> obs = new ArrayList<Observer>();
public void subsribe(Observer ob) {
obs.add(ob);
}
void notis() {
for (int i = 0; i < obs.size(); i++) {
obs.get(i).noti();
}
}
void upload() {
System.out.println("영상 업로드 완료");
notis();
}
}
// 구독자
interface Observer {
void noti();
void subsribe(Youtuber);
}
class ObserverA implements Observer {
@Override
public void noti() {
System.out.println("- A 유튜브 alarm !!");
}
}
class ObserverB implements Observer {
@Override
public void noti() {
System.out.println("- B 유튜브 alarm !!");
}
}
-----------------------------------------------------------------------
(응용)
구독자가 유투버 선택하는 경우
import java.util.ArrayList;
public class main {
public static void main(String[] args) {
Youtuber host1 = new Youtuber();
Youtuber host2 = new Youtuber();
Observer ob1 = new ObserverA();
Observer ob2 = new ObserverB();
// 유투버가 구독자를 선택
//host.subsribe(ob1);
//host.subsribe(ob2);
// 구독자가 유투버 선택
ob1.subscribe(host1);
ob2.subscribe(host1);
ob1.subscribe(host2);
host1.upload();
host2.upload();
}
}
class Youtuber {
private ArrayList<Observer> obs = new ArrayList<Observer>();
public void subsribe(Observer ob) {
obs.add(ob);
}
void notis() {
for (int i = 0; i < obs.size(); i++) {
obs.get(i).noti(this);
}
}
void upload() {
System.out.println(this+" 영상 업로드 완료");
notis();
}
}
// 구독자
interface Observer {
void noti(Youtuber y);
void subscribe(Youtuber y); // 구독자가 subsribe 하도록 정의
}
class ObserverA implements Observer {
@Override
public void noti(Youtuber y) {
System.out.println("- A 유튜브 alarm !!" + y);
}
public void subscribe(Youtuber y) { // 여기서 subscribe 하는 method를 호출
y.subsribe(this);
}
}
class ObserverB implements Observer {
@Override
public void noti(Youtuber y) {
System.out.println("- B 유튜브 alarm !!" + y);
}
@Override
public void subscribe(Youtuber y) {
y.subsribe(this);
}
}
구현 예제 - 키보드
import java.util.ArrayList;
import java.util.HashMap;
public class main {
public static void main(String[] args) {
OS os = new OS();
Button btn1 = new Button("Button-1");
Button btn2 = new Button("Button-2");
// 버튼 추가
os.addButton(btn1);
os.addButton(btn2);
// Observer 등록
btn1.subscribe(new Obs());
// 버튼 클릭
os.pushButton(btn1);
}
}
class OS {
HashMap<String, Button> map = new HashMap<String, Button>();
void addButton(Button btn) {
if (map.containsKey(btn.getName())) {
System.out.println("ERROR: 이미 등록된 버튼");
return;
}
map.put(btn.getName(), btn);
}
void pushButton(Button btn) {
btn.userClick();
}
}
class Button {
private ArrayList<Observer> obs = new ArrayList<Observer>();
private String name;
Button(String name) {
this.name = name;
}
void subscribe(Observer ob) {
obs.add(ob);
}
String getName() {
return name;
}
void userClick() {
for (int i = 0; i < obs.size(); i++) {
obs.get(i).noti();
}
}
}
interface Observer {
void noti();
}
class Obs implements Observer {
@Override
public void noti() {
// Button cliek되면 개발자가 작성해야 하는 코드
System.out.println("버튼이 클릭되었습니다");
}
}
'Software Architect' 카테고리의 다른 글
[Design Pattern] Command / Strategy / State Pattern (0) | 2022.03.25 |
---|---|
[Design Pattern] Flyweight pattern (0) | 2022.03.25 |
[Design Pattern] Decorator Pattern (0) | 2022.03.24 |
[Design Pattern] Adapter Pattern (0) | 2022.03.24 |
[Design Pattern] Facade Pattern (0) | 2022.03.24 |