상세 컨텐츠

본문 제목

디자인패턴02 - Observer 패턴_ Java

Design Pattern with Java & Swift

by 앱등개발자IOS 2022. 9. 29. 12:49

본문

# 옵저버 패턴  ( = Publish/Subscribe 패턴)

## 정의 : 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고, 자동으로 내용이 갱신되는 방식으로, "일대다 의존성"을 정의한다.

## 키워드 : One-to-Many

## 목적 : 상태 변화(State change)를 다른 다수의 객체들에게 알리기 위함

## 하나의 Object는 옵저버이자 Subject일 수 있다!!!

옵저버 패턴은 여러 방식으로 구현할 수 있지만, 보통 클래스 디자인으로 구현한다.

## 언제 사용하는가?

    - Loose Coupling이 필요할 때 : 객체들이 상호작용할 수는 있지만, 서로를 잘 모르는 관계

        => 옵저버는 구상 클래스가 무엇인지, Observer가 무엇을 하는지 알 필요도 없다.

        => 새로운 Observer를 추가할 때도, Subject코드를 전혀 변결할 필요가 없어진다.

        => Subject와 Observer는 독립적으로 재사용하고, Observer가 달라져도 서로 영향을 미치지 않는다.

 

    - Broadcasting이 필요할 때 

    - State change가 다른 object의 어떤 behavior를 trigger 해야할 때

    - notification 에 필요한 비용에 부담이 없을 때

 

## Observer Pattern이 적용되지 않았을 때의 예시

### 배경 : WeatherData는 기상 측정 센서로부터 데이터를 받아와, 정보를 사용자에게 보여주는 단말기에 정보를 뿌려주는 역할을 한다.

 

위 코드의 단점 

1. 인터페이스 바탕X 구현체 바탕으로 코딩하고 있다.

2. 새 디스플레이 항목이 추가되면, 항상 Hard-Coding해야한다.

3. 실행 중, 디스플레이 항목을 추가하거나 제거할 수 없다.

4. 바뀌는 부분 Encapsulation 하지 않았다.

 

해결해야할 것들 

1. 모든 display들이 concrete implemented 되어있으므로, 항목이 추가/제거 될 때 Hard-Coding하지 않게 설계해야함(바뀔 수 있는부분 캡슐화)

2. 모두 update() 함수를 호출하므로, 이 부분 캡슐화 필요

 

    - WeatherData class 인스턴스는 는 기상 측정 센서로부터 Data가  갱신될 때마다 measurementsChanged()함수를 호출하여 데이터를 갱신하고, 해당 데이터를 디스플레이에 update해준다.

=> 주어진 역할은 모두 잘 해줄 수 있으나, ( temp, humidity, pressure) 외의 새로운 데이터가 들어올 때마다 Hard-Coding해야하는 단점이 있어 유지보수가 귀찮아진다. 

 

 

## Observer Pattern이 적용되었을 때의 예시

 

    - 1. Subject에서 갱신된 정보를 전달하는 방법을 제공하기 위한 Observer인터페이스를 각 Concrete class들이 구현

    - 2. 모든 Display요소들이 갖고있는 display()기능을 인터페이스로 구현 

    - Subject인 WeatherData는 각 concrete class들이 Observer인터페이스를 구현하여, update()메서드를 구현하고있다는 것 외에는 알고있는 것이 없다!

    - 하지만 각 Concrete class들은 subject , 즉 WeatherData에 대해 더 많이 알고있다. 

 

Subject 구현부 특징 정리

- Subject는 registerObserver(Observer o)메서드로 옵저버를 내부 List<Observer>에 저장하여 관리.

- removeObserver(Observer o)로 옵저버를 제거

- notifyObservers()메서드로 옵저버들에게 알림

- notifyObservers()를 구현하면서는, List내부의 Observer를 돌며 public으로 선언된 observer.update()메서드를 호출한다.

 

Concrete Class 구현부 특징 정리

- 생성자에 Subject 객체를 전달하여 해당 Subject의 Observer리스트에 register한다.

- update()함수를 구현하여 데이터를 갱신

 

## Push방식을 Pull방식으로 바꾸기 

    - Push방식을 Pull방식으로 바꿀 수도 있다. (단순 구현의 차이)

update(){
this.temp = subject.getTemp();

}와 같이, 

update()함수 매개변수를 모두 없애고, update함수 내부에서 해당 concrete class에서 필요한 정보들만 subject의 public으로 선언된 getter 메서드를 사용하여 가져오는 pull방식이 된다.

(일반적으로 Pull방식이 더 옳은 방식으로 여겨진다.)

 

 

 

 

관련글 더보기