옵저버 패턴

2020. 2. 20. 01:14컴퓨터 과학/디자인 패턴

옵저버 패턴(Observer Pattern)

주제가 되는  객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들(옵저버)한테 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의한다.  대부분 주제 인터페이스와 옵저퍼 인터페이스가 들어있는 클래스 디자인을 바탕으로 한다.

 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many)의존성을 정의한다.

 

옵저버 패턴의 주요 특징

  • 자료 제공 클래스는 게터메서드가 있다.
  • 새로운 데이터가 나올 때마다 디스플레이를 갱신하는 메서드가 호출된다.
  • 시스템이 확장 가능해야 된다.
  • 옵저버에게 연락이 가는 순서에 의존하면 안된다.-> 느슨한 결합을 위반하기 때문이다. 특정 연락 순서에 의존하도록 코드를 만들었다면 그 방법이 잘못된 것이다. 특정 연락 순서에 의존하도록 만들었다면, Observable / Observer 클래스의 구현을 변경했을 떄 연락순서가 바뀌면 다른 결과가 나올 수 있기 때문이다.

옵저버의 특징

각 옵저버마다 구성요소가 다를수 있다는걸 알아야 한다. 각 옵저버는 공통된 인터페이스를 구현해야 구성 요소의 형식이 달라도 주제 객체에서 측정값을 보낼 수 있다.

 

느슨한 결합(Loose coupling)

두 객체가 느슨하게 결합되어 있다는 것은, 그 둘이 상호작용을 하긴 하지만 서로에 대해 잘 모른다는 것을 의미한다. 옵저버 패턴에서는 주제와 옵저버가  느슨하게 결합되어 있는 객체 디자인을 제공한다.  주제가 옵저버에 대해서 아는것은 옵저버가 특정 인터페이스를 구현한다는 것 뿌이다 .옵저버의 구상 클래스가 무엇인지, 옵저버가 무엇을 하는지 등에 대해서는 알 필요가 없다.

 옵저버는 언제든지 새로 추가할 수 있다. 주제는 Observer 인터페이스를 구현하는 객체의 목록에만 의존하기 때문에 언제든지 새로운 옵저버를 추가할 수 있다.

 새로운 형식의 옵저버를 추가하려고 할 때도 주제를 전혀 변경할 필요가 없다. 새로운 클래스에서 Observer 인터페이스를 구현하고 옵저버로 등록하기만 하면 도니다. 주제 객체는 전혀 신경도 쓰지 않는다. Observer인터페이스만 구현한다면 어떤 객체에든지 연락한다.

 주제와 옵저버는 서로 독립적으로 재사용할 수 있다. 주제나 옵저버를 다른 용도로 활용할 일이 있다고 해도 손쉽게 재사용할 수 있다. 그 둘이 서로 단단하게 결합되어 있지 않기 때문이다.

 주제나 옵저버가 바뀌더라도 서로한테 영향을 미치지는 않는다. 둘이 서로 느슨하게 결합되어 있기 때문에 주제 혹은 옵저버 인터페이스를구현한다는 조건만 만족된다면 어떻게 바꿔도 문제가 생기는 일은 없다. 느슨한 결합을 활용했을 때는 객체 사이의 상호 의존성을 최소화할 수 있다.

 

 

 

자바 내장 옵저버 패턴

  • java.util.Obserbable
  • java.utilObserver

 

Obserbable.class

클래스이다. 서브클래스를 만들어야 한다. 그래서 재사용성에 제약이 생기게 된다. 그리고 Obserbable인터페이스라는 것이 없기 때문에 자바에 내장된 ObserverAPI하고 잘맞는 클래스를 직접 구현하는 것이 불가능하다. java.util 구현을 다른 구현으로 바꾸는 것도 불가능하다.

 

Obserable의 주요 2가지 메서드 : setChanged(), notifyOberservers()

setChanged()

객체의 상태가 바뀌었다는 것을 알린다. 나중에 notifyOberservers()를 호출할 떄 그 메소드에서 옵저버들을 갱신시키게 된다. setChanged()가 호출되지 않은 상태에서 notifyObservers()가 호출되면 옵저버들한테 아무 연락도 가지 않게 된다. setChanged()는 연락을 최적화할 수 있게 해 줌으로써 옵저버들을 갱신하는 방법에 있어서 더 광범위한 유연성을 제공하기 위해 만들어진 것이다.

 

notifyObservers(Object args)

옵저버들에게 바뀐 상태를 전달한다. 옵저버들한테 연락을 하고 나면 setChanged()가 다시 사용될 수 있게 변화를 나타내는 플래그 값을 재설정한다. pull모델의 경우에는 상태만 업그레이드하고 각 옵저버들에게 값을 전달하지 않는 경우도 있다.