일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- 운동
- 개발
- FrameLayout
- Android Universal Image Loader
- FragmentSatePagerAdapter
- TabLayout and ViewPager
- BottomNavigationViewEx
- 재태크
- 독서
- FragmentPagerAdapter
- overridePendingTraction
- 2020년 목표
- 목표한번이뤄보자
- Today
- Total
seops
[Concepts] Observer Pattern 본문
[ 정의 ]
※ Observer Pattern이란?
me) Subject와 Observer들로 구성되며(일 대 다), 데이터를 포함한 객체가 변화하게 되면 Observer들에게 알려주는 패턴
- 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들에게 연락이 가고, 자동으로 내용이 갱신되는 방식으로 '일대다' 의존성을 정의
- 데이터의 주인은 Subject이며, Observer는 데이터가 변경되었을 때, Subject에서 갱신해 주기를 기다리는 입장이기 떄문에 의존성을 갖음
- 느슨하게 결합하는 디자인을 사용하면 변경 사항이 생겨도, 무난히 처리할 수 있는 유연한 객체지향 시스템을 구축할 수 있음 (객체 사이의 상호의존성 최소화)
[ 구현 ]
※ Subject
public interface Subject {
public void registerObserver(Observer o);
public void unregisterObserver(Observer o);
public void notifyObservers();
}
public class WeaterData implements Subject {
private ArrayList observers;
private float temperature;
...
public WeatherData() {
observers = new ArrayList();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void unregisterObserver(Observer o) {
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
public void notifyObservers() {
for(int i = 0; i < observers.size(); i++) {
Observer observer = (Observer) observers.get(i);
observer.update(Data);
}
}
...
}
- Observer 객체들을 저장하기 위해, ArrayList를 추가
※ Observer
public interface Observer {
pubilc void update(Data data) {
}
public class CurrentConditionsDisplay implements Observer {
private Subject weatherData;
private Data data;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
....
}
[ 보충 ]
※ Java API > 내장 Observer Pattern
- Interface Subject -> Class Observable
- Interface Observer -> Interface Observer
- ConcreteSubject 클래스가 Observable 클래스를 상속 받아야 함
- Observer가 연락을 받는 방법으로는 2가지 방식 존재
1) Push
- Observer 인터페이스의 update 메소드 호출 시, 구체적인 인자를 통해 전달 받는 방식
- update(int humidity, int degree)
2) Pull
- Observer 인터페이스의 update 메소드 호출 시, Observable과 Object 객체를 통해 전달 받는 방식
public void update(Observable obs, Object args) {
if(obs instantod WeatherData) {
WeatherData weatherData = (WeatherData) obs;
this.temperature = weatherData.getTemperatrue();
this.humidity = weatherData.getHumidity();
display();
}
}
※ 주의 사항
- Observer의 연락 순서에는 의존하면 안됨
~ 순서가 바뀐다고 해서 다른 결과가 나온다면, 그것은 '느슨한 결합'이라고 할 수 없음
~ 객체 사이의 상호 의존성 증가
※ 단점
- Observable이 클래스이기 때문에, 서브 클래스를 만들어야 한다는 문제점 발생 ~ 재사용성의 제약이 생김
- Observable 인터페이스라는 것이 없기 때문에, 자바에 내장된 Observer API와 맞는 클래스 구현 불가
[ 추가 ]
※ 주의 사항
- 삭제한 Subject들에 대한 무효 참조자를 계속 유지할 때가 있음
~ Subject의 삭제로 Observer가 무효 참조자를 갖게 되도록 만들면 안됨
- 복잡한 갱신의 의미 구조를 캡슐화
1) Subject와 Observer 간에 발생하는 관련성이 복잡하다면, 이들 관련성을 관리하는 별도의 객체를 만듦
2) 예시
- 연산의 수행으로 여러 개의 서로 관련된 주체를 변경해야 한다고 가정
- 이때, 모든 Subject가 수정되고 나서 이 Subject의 Observer에게는 딱 한 번만 통보되어야 한다.
3) 별도 객체(ChangeManager)는 아래 사항을 책임져야 함
- Subject와 Observer를 Mapping하고, 이를 유지하는 인터페이스를 정의
- Subject는 자신들의 Observer가 누구인지, Observer는 자신들의 Subject가 누구인지 관리할 필요 없음
- Subject에게 요청이 있을 때, 모든 독립적 Observer 수정
public interface ChangeManager {
public abstract void register(Subject subject, Observer observer);
public abstract void unregister(Subject subject, Observer observer);
public abstract void notifyObservers(Subject subject);
}
public class ConcreteChangeManager implements ChangeManager {
Map<Subject, List<Observer>> mapping;
public ConcreteChangeManaer() {
mapping = new HashMap<Subject, List<Observer>>();
}
@Override
public void register(Subject subject, Observer observer) {
if(mapping.containsKey(subject)) {
mapping.get(subject).add(observer);
} else {
mapping.put(subject, new ArrayList<Observer>(Arrays.asList(observer)));
}
}
@Override
public void unregister(Subject subject, Observer observer) {
if(mapping.containsKey(subject)) {
if(mapping.get(subject).contains(observer)) {
mapping.get(subject).remove(observer);
}
}
}
@Override
public void notifyObservers(Subject subject) {
for(Observer observer : mapping.get(subject)) {
observer.update(subject);
}
}
}
[ 참고 (Reference) ]
1. Book > Head First Design Pattern
2. Book > GoF Design Pattern
3. Code >
csparpa/gof-design-patterns
Original GoF design patterns in multiple languages - csparpa/gof-design-patterns
github.com
'Android > Design Pattern' 카테고리의 다른 글
[Concepts] Factory Method Pattern (0) | 2020.04.14 |
---|---|
[Development] Observer Pattern (0) | 2020.03.30 |