Whiteship's Note


2장 Observer Pattern(끝)

Design Pattern : 2006.10.05 10:37


Observer pattern

From Wikipedia, the free encyclopedia

Jump to: navigation, search
It has been suggested that Event listener be merged into this article or section. (Discuss)

The observer pattern (sometimes known as publish/subscribe) is a design pattern used in computer programming to observe the state of an object in a program. It is related to the principle of Implicit invocation.

This pattern is mainly used as a poor man’s event handling system.In some programming languages, the issues addressed by this pattern arehandled in the native event handling syntax.

The essence of this pattern is that one or more objects (called observers or listeners) are registered (or register themselves) to observe an event which may be raised by the observed object (the subject). (The object which may raise an event generally maintains a collection of the observers.)

The UML diagram below illustrates this structure:



원문에 보시면 더 자세한 설명이 있습니다. 간략히 보면..

객체의 상태를 관찰하기 위한 디자인 패턴이라고 합니다.
주로 사용되는 곳은 event handling system이라고 합니다.
책이도 잠깐 나오지만 java의 수많은 이벤트 핸들링이 옵저버 패턴을 사용한 것인데 정말 놀랍지 안나요. ㅎㅎ

이 글을 보시면 옵저버 패턴을 어떻게 적용할 수 있을까요? 라는 질문에 대한 답변이 올라와 있는데요.

질문은 다음과 같습니다.
답변은 먼저 문제를 파악하고, 패턴을 이해하고, 그 다음 적용하라는 이야기를 해주고..
Java code로 예제를 제시해 줍니다.

마지막으로 observer pattern을 적용할 수 있는 경매장 예제를 보면서 마무리를 하겠습니다.

위 상황에 맞도록 다음주 월요일까지 과제를 해야 합니다. ㅠㅠ

'Design Pattern' 카테고리의 다른 글

Strategy Pattern 예제(끝)  (0) 2006.10.08
Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제  (0) 2006.10.08
Head First Degisn Patterns 소스코드 다운받기.  (0) 2006.10.08
2장 Observer Pattern(끝)  (0) 2006.10.05
2장 Observer Pattern(계속)  (2) 2006.10.05
2장 Observer Pattern(계속)  (0) 2006.10.05
2장 Observer Pattern  (0) 2006.10.05
1장 Strategy Pattern (끝)  (0) 2006.09.26
1장 Strategy Pattern(계속)  (2) 2006.09.26
top


2장 Observer Pattern(계속)

Design Pattern : 2006.10.05 10:28


기상 스테이션

복잡해 보일 수도 있지만 매우 간단한 class diageam입니다. 각각의 display들이 Display interface를 구현하도록 추가한 것만 빼면 기본적인 observer패턴의 모습과 같습니다.
WeatherData class에는 observer들을 등록, 삭제할 List를 가지고 있어야 합니다. 그래야 나중에 상태가 바뀌었을 때(measurementsChanged()가 호출됐을 때) notifyObservers() 메소드에서 자신의 정보를 원하는 옵저버들에게 정보를 줄 수 있겠죠.
정보를 전달하는 방법은 옵저버들이 가지고 있는 update 메소드를 호출하여 update 메소들의 인자로 data를 넘기는 방법을 사용합니다. 이 방법은 subject에서 정보가 바뀔때 마다 모든 옵저버들에게 정보를 넘겨주는 방식으로 push 하는 방식입니다.
이러한 방법의 단점은 옵저버가 원하든 원치 않든 등록되어 있으면 무조건 정보가 바뀔 때 마다 갱신 받는 것입니다.(물론 그러고 싶어서 등록한거겠지만 가끔가다 단체로 가족여행 갔을 때 신문이 쌓여 있으면 도둑이 들기 쉽기 때문에 잠깐만 신문배달을 중지하고 싶기도 하겠죠..)
따라서 무조건 받는 방법 말고 옵저버가 원할 때 원하는 정보만 가져 갈 수 있도록 하는 pull방식을 사용하는 것이 유용할 때도 있습니다.
그리고 자바 API에 이미 pull방식과 push방식이 모두 가능한 class들을 구현해 두었습니다.
(update의 인자로 Observale객체 자체를 넘기도록 구현해 두었습니다. 구독자 입장에서는 원하는 시점에서 원하는 정보를 getter를 사용해서 가져가면 되기 때문이지요.)
앞에서 보았던 Subject interface에 해당하는 것이 java의 Observable abstract class입니다. class이기 때문에 상속을 사용해야겠지요.

java.util
Class Observable

java.lang.Object  extended byjava.util.Observable
setChanged() 메소드는 객체의 정보가 바꼈는지 체크하는 플래그를 true로 만드는 메소드입니다. 이 메소드를 사용하면 매번 정보가 바뀔 때마다 알려주는 것이 아니라 subject에서 알려주고 싶을 때 알리도록 조절할 수 있다는 유용함이 생기겠네요.
그리고 다음은 앞에서 보았던 Observer와 거의 같은 Observer 인터페이스입니다.
notifyObservers() 메소드가 Observer 인터페이스에 있는 update() 메소드를 호출할 것입니다.


update의 인자가 우리가 사용한 것( update( teperature, humidity, pressure) )와는 약간 다르네요. 처음에 넘겨주는 것이 observeable( subject 객체 ) 그리고 정보를 객체형태로 넘겨줍니다.
이 둘을 이용해서 class diagram을 수정하면 다음과 같습니다.

자바에 내장된 옵저버 패턴을 사용하려면
먼저 옵저버가 되어야 하기 때문에 addObserver() 메소드를 호출하면 되고 탈퇴하고 싶을 때는 deleteObserver()를 호출하면 됩니다.
이 부분은 전에 사용한 방법과 같습니다 단지 메소드 이름만 바뀐거죠.
다음으로 달라진 부분인데 바로 정보를 전달하는 부분입니다.
연락을 돌리려면 먼저 setChanged()를 호출해서 바꼈다는 flag를 true로 만들어 주어야 합니다.
그리고 그 다음에 notifyObservers() 또는 notifyObservers(Object arg) 를 호출하여 그 내부에서 옵저버에 있는 update(Observable o, Object arg)를 호출하도록 합니다.
전에 사용하던 방법에 setChanged()를 호출하는 부분이 추가 된 것입니다.
이렇게 함으로써 정말 필요로도 할 때 정보를 갱신할 수 있는 유용함이 생기는 것입니다.
아! 그리고 update 메소드에 subject객체 자체를 보내기 때문에 이 객체에 있는 getter를 통해서 원하는 정보만 가져갈 수도 있게 되었군요.
풀방식을 이런식으로 사용할 수 있었네요 ㅎㅎ
p106에 제일 하단의 음영처리된 부분에 있는 gettere들을 보시면 무슨 말인지 이해하실 수 있을 것입니다.
그리고 또 차이점이 있는데
연락을 돌리는 순서가 옵저버들이 등록된 순서에 의존하지 않는 다는 것입니다.
(신문 배달이 옆집다음에 우리집에 주든 우리집에 주고 옆집을 주든 별 상관이 없죠? 신문을 받는 다는것 자체가 중요하죠.)

'Design Pattern' 카테고리의 다른 글

Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제  (0) 2006.10.08
Head First Degisn Patterns 소스코드 다운받기.  (0) 2006.10.08
2장 Observer Pattern(끝)  (0) 2006.10.05
2장 Observer Pattern(계속)  (2) 2006.10.05
2장 Observer Pattern(계속)  (0) 2006.10.05
2장 Observer Pattern  (0) 2006.10.05
1장 Strategy Pattern (끝)  (0) 2006.09.26
1장 Strategy Pattern(계속)  (2) 2006.09.26
1장 Strategy Pattern  (0) 2006.09.26
top


2장 Observer Pattern(계속)

Design Pattern : 2006.10.05 10:13


신문을 구독하는 방법과 동일 합니다.
책에는
출판사 + 구독자 = 옵저버 패턴
이라고 큼지막하게 쓰여있네요.
출판사는 주제(subject)로 부르고 구독자는 옵저버(observer)라고 부르도록 하겠습니다.
앞에서 본 예제에 적용하면 weatherData 객체가 subject 그리고 각종 display장치들이 옵져버에 해당합니다.
위 기본 설정을 중간에 잊어버리시면 앞으로 진행되는 설명을 이해하는데 막대한 지장이 있을 것입니다.
주제와 옵저버가 어떤 식으로 상호 작용하는지 살펴보겠습니다.

기본적으로 subject를 구독하기로 등록한 observer들 에게 소식을 전해줍니다.
( 나중에 가면 subject의 정보가 변할 때 마다 subject가 주는 push방법과 observer들이 원하는 정보만 가져 갈 수 있는 pull방법이 나옵니다. )
Observer가 아닌 객체는 observer가 되려면 다음과 같이 subject에 자기도 등록 해달라고 요청하면 됩니다.

그럼 이제 요청한 객체 역시 다른 observer들과 마찬가지로 subject의 정보가 바뀔 때 마다 새로운 정보를 받을 수 있게 됩니다.
그러다 더이상 subejct의 정보를 구독하길 원치 않는다면 즉 탈퇴하고 싶다면 아래와 같이 탈퇴하고 싶다고 subject에 요청하면 됩니다.

이러면 이제 subject에서는 더이상 그 객체에게 자신의 정보를 보내지 않습니다.
옵저버 패턴의 정의는 다음과 같습니다.
옵저버 패턴에서는 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(ont-to-many)의존성을 정의합니다.
subject가 일 옵저버들이 다 그리고 당연히 옵져버들이 subject에 의존하고 있는 위의 그림들을 보면 쉽게 이해할 수 있습니다.

subject에 있는 세개의 메소드 중에서 첫 번째 보이는 notifyObserves 메소드에서는 자신의 정보를 모든 옵저버들에게 알려주기 위해서 옵저버들이 가지고 있는 update 메소드를 호출하여 알려 줄 것입니다.
subject와 옵저버는 서로 결합된 관계지만 subject는 사실 누가(어떤 옵져버)가 자신의 정보를 원하는지 확실히 모르고 있습니다. 누군가 갑자기 등록하기도 하고 더 이상 관심없다며 탈퇴하기 때문이지요. 또한 그러한 일들로 인해서 subject에 있는 코드가 바뀔일도 없습니다. 이렇게 유연한 관계의 결함을 느슨한 결합(Loose coupling)이라고 합니다.
여기서 새로운 디자인 원칙 하나가 추가됩니다.
디자인 원칙4
서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.
자 그럼 위에서 살펴본 observer 패턴을 다시 기상 스테이션 설계에 적용해 봅시다.

'Design Pattern' 카테고리의 다른 글

Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제  (0) 2006.10.08
Head First Degisn Patterns 소스코드 다운받기.  (0) 2006.10.08
2장 Observer Pattern(끝)  (0) 2006.10.05
2장 Observer Pattern(계속)  (2) 2006.10.05
2장 Observer Pattern(계속)  (0) 2006.10.05
2장 Observer Pattern  (0) 2006.10.05
1장 Strategy Pattern (끝)  (0) 2006.09.26
1장 Strategy Pattern(계속)  (2) 2006.09.26
1장 Strategy Pattern  (0) 2006.09.26
top


2장 Observer Pattern

Design Pattern : 2006.10.05 10:10


엠파스 블러그에서 가져옵니다.

너무도 많이 들어본 이름.. 옵져버 스타크래프트의 럴커나 다템 같은 안보이것 까지 볼 수 있는 유닛이다.
게임 중 후반에 이르러 옵져버가 있으면 상대방이 어디에 무슨 병력을 얼만큼 갖다 놨는지 무슨 건물을 짓고 있는지 훤히 알 수 있기 때문에 매우 중요한 유닛이다.
사설은 이만 하고 본론으로 들어갑니다.
책의 첫 부분에 기상 모니터링 애플리케이션 개요가 나오고 있습니다.


여기서 우리가 구현해야 할 부분은 WeatherData객체가 데이터를 취득하는 부분과 디스플레이 장비에서 기상 상태를 화면에 표시하는 부분입니다.
그렇다면 기본적으로 WeatherData class에는 기상 스테이션으로 부터 습도, 온도, 압력 data를 가져오는 메소드들을 구현해야 할 것입니다. 그리고 매번 상태가 바뀔때마다 현재 객체가 가지고 있는 습도, 온도, 압력 값을 바꿔 주어야 하며 디스플레이 장비에도 새로운 정보를 바탕으로 표시 해주어야겠지요..
따라서 다음과 같은 class diagram을 그릴 수 있습니다.

이 class의 일부를 구현하면 다음과 같이 됩니다.
public class WeatherData {
  public void measurementsChanged() {
     
       float temp = getTemperature();
       float humidity = getHumidity();
       float pressure = getPressure ();
      
       currentConditionDisplay.update( temp, humdity, pressure );
       statisticsDisplay.update( temp, humdity, pressure );
       forecastDisplay.update( temp, humdity, pressure );
  }
}
이 코드를 보면 display하는 class들과 다음과 같은 관계가 있다는 것을 알 수 있습니다.

이 때 문제는 measurementsChanged()에서 특정 구현된 class들에 의존한다는 것입니다.
1장에서 보았던 구현이 아닌 인터페이스를 사용하라던 원칙에 위배됩니다.
그나마 다행인 것은 Display interface를 사용하여 method이름은 update()라는 공통의 이름을 사용한다는 것인데.. 어차피 특정 구현에 의존한다면 별로 장점이 없다고 생각합니다.
그리고 만약에 새로운 Display형태가 추가되면 measurementsChanged의 코드 역시 바껴야 한다는 것입니다.
이러한 문제점을 보안하려면 어떻게 해야할까요 먼저 옵져버 패턴을 공부한 뒤에 해결하도록 합시다.
투비 컨티뉴드

여기서 하나 의문점...

WeatherData 객체가 있고 이를 구독하는 Display들이 있습니다. 그리고 WwatherData의 정보를 바꾸는 무언가가 있습니다. 여기서는 이 무언가가 기상스테이션이죠.
그런데 WeatherData 클래스를 보시면 getter들이 셋이 있는데 이 getter들은 자신의 정보를 다른 클래스에 넘겨주는 accessor 역할을 하는 것이 아니라 기상스테이션에서 정보를 가져오는 역할을 하고 있습니다. 이부분은 뭔가 잘못된 것이 아닌가.. 생각해봅니다.

'Design Pattern' 카테고리의 다른 글

Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제  (0) 2006.10.08
Head First Degisn Patterns 소스코드 다운받기.  (0) 2006.10.08
2장 Observer Pattern(끝)  (0) 2006.10.05
2장 Observer Pattern(계속)  (2) 2006.10.05
2장 Observer Pattern(계속)  (0) 2006.10.05
2장 Observer Pattern  (0) 2006.10.05
1장 Strategy Pattern (끝)  (0) 2006.09.26
1장 Strategy Pattern(계속)  (2) 2006.09.26
1장 Strategy Pattern  (0) 2006.09.26
top


1장 Strategy Pattern (끝)

Design Pattern : 2006.09.26 00:23


최종적으로 위와 같은 다이어그램이 완성됩니다.
상속으로 시작했던 디자인이 composition(구성)을 사용함으로써 결말이 났군요.
이로써 다음과 같은 디자인 원칙을 배울 수 있습니다.
디자인 원칙3
상속보다는 구성을 활용한다.
위에서 했던 행동들이 하나의 디자인 패턴으로 정립되어 있었습니다.
바로 Strategy pattern 이라는 것으로 써 정의는 다음과 같습니다.
Strategy Pattern에서는 알고리즘군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있돌고 만든다. 이것을 사용하면 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있다.
위키피디아 에서 정의한 내용은 다음과 같습니다.

Strategy pattern

From Wikipedia, the free encyclopedia

Jump to: navigation, search
In computer programming, the strategy pattern is a particular software design pattern, whereby algorithms can be selected on-the-fly at runtime.
In some programming languages, such as those without polymorphism, the issues addressed by this pattern are handled through forms of reflection, such as the native function pointer or function delegate syntax.
The strategy pattern is useful for situations where it is necessary to dynamically swap the algorithms used in an application. The strategy pattern is intended to provide a means to define a family of algorithms, encapsulate each one as an object, and make them interchangeable. The strategy pattern lets the algorithms vary independently from clients that use them.
runtime시에 알고리즘을 선택할 수 있는 특징이 있고 다형성이 지원되지 않는 언어의 경우 포인터와 delegate syntax와 같은 reflection의 형태로 다뤄집며 유용한 상황으로는 동적으로 알고리즘을 바꾸고 싶을 경우라고 간략히 요약할 수 있습니다.
원문은 위의 링크와 같으며 예제로 여러가지 sorting 알고리즘을 동적으로 바꿔가며 사용해보는 예제가 C++언어로 나와있습니다.
더 구체적인 내용은 이곳에서 볼 수 있습니다.
decoupling에 관한 내용과 여러 장점에 대해 설명이 되어 있습니다.
다음은 기본 Strategy Pattern의 기본 UML입니다.
마지막으로 실생활에 Strategy Pattren을 적용한 예를 살펴보겠습니다.

'Design Pattern' 카테고리의 다른 글

Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제  (0) 2006.10.08
Head First Degisn Patterns 소스코드 다운받기.  (0) 2006.10.08
2장 Observer Pattern(끝)  (0) 2006.10.05
2장 Observer Pattern(계속)  (2) 2006.10.05
2장 Observer Pattern(계속)  (0) 2006.10.05
2장 Observer Pattern  (0) 2006.10.05
1장 Strategy Pattern (끝)  (0) 2006.09.26
1장 Strategy Pattern(계속)  (2) 2006.09.26
1장 Strategy Pattern  (0) 2006.09.26
top


1장 Strategy Pattern(계속)

Design Pattern : 2006.09.26 00:20


이전 글에서 발생했던 문제를 해결하기 위해서 interface를 사용하여 날아다닐 수 있는 오리와 소리낼 수 있는 오리로 구분하였습니다.
날아 다니거나 소리 낼 수 있는 오리들은 해당 interface를 구현해야 하며 따라서 fly나 quack과 같은 method들을 구현해 주어야 합니다.
만약에 이런 상황에서 오리의 소리가 공통적으로 바뀐다면 어떻게 해야할까요? 아마 Quackable을 구현한 모든 class들을 수정해야 할 것입니다.
(현재는 class들의 수가 몇개 안되지만 50개 라고 하면 50번을 수정해야 합니다.)
좀더 좋은 방법이 필요할 듯합니다.
지금까지 계속 변화를 가정하여 class들이 보다 유연하게 구성되도록 진행되가고 있습니다.(그만큼 변화가 빈번히 일어난다는 것이겠죠.)
이러한 변화 속에서 살아남으려면 다음과 같은 디자인 원칙에 유의해야합니다.
디자인원칙1
애플리케이션에서 달라지는 부분을 찾아 내고, 달라지지 않는 부분으로부터 분리시킨다.
즉 fly()와 quack()은 Duck class에서 오리마다 달라지는 부분입니다.
이 두 메소드를 Duck에서 뽑아 내어 새로운 class집합으로 만들 것입니다.
이 class집합들은 다음의 디자인 원칙에 따라 구현합니다.
디자인원칙2
구현이 아닌 인터페이스에 맞춰서 프로그래밍한다.
이 말은 선뜻 이해가 되지 않습니다.
여기서 구현이라고 하는 것은 특정 class에 있는 method를 말하는 것이고 인터페이스는 상위 classl에 있는 method들을 말한다고 생각합니다.
즉.. Animal a = new Dog(); or new Cat();
a.eat();
을 실행했을 때 개도 먹일 수 있고 고양이도 먹일 수 있도록 프로그래밍 하라는 뜻으로 이해가 됩니다.
(저 방법 보다 Animal a = getAnimal(); 이런 방법으로 new 키워드를 없애는 것이 보다 더 디자인원칙2를 잘 지키는 것이라고 나와있습니다.)
따라서 다음과 같은 다이어 그램으로 class집합을 구현할 수 있습니다.

이제 Duck class에서는 위 두 집합의 상위Type의 변수를 가진다면 a.eat()과 같은 장점(다형성)을 누릴 수 있습니다.
위와 같이 FlyBehavior와 QuackBehavior type의 변수를 가지고 있고
performFly()와 performQuack()에서는
flyBehavior.fly()와 quackBehavior.quack()를 실행하기만 하면 됩니다.
이렇게 해두면 각각의 오리( sub class )들은 dispaly()만 구현하면 되고 자기 자신의 quack이나 fly의 Behavior가 어떤 것인지 설정해 줌에 따라 결과가 달라지게 됩니다.
자신의 Behavior를 설정하는 방법은 객체 생성시에 생성자에서 하는 방법과
나중에 setter메소드를 사용하는 방법이 있습니다.
setter메소드를 이용하여 Behavior를 지정해 줄 경우 날수 없던 오리(FlyNoWay Behavior로 setting했던 오리)가 갑자기 날개를 가지고 날아갈 수있게(FlyWithWings Behavior로 오리의 Behavior를 프로그램 실행도중 setter method를 사용하여 setting하면 됩니다.) 마술을 부릴 수도 있습니다.

'Design Pattern' 카테고리의 다른 글

Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제  (0) 2006.10.08
Head First Degisn Patterns 소스코드 다운받기.  (0) 2006.10.08
2장 Observer Pattern(끝)  (0) 2006.10.05
2장 Observer Pattern(계속)  (2) 2006.10.05
2장 Observer Pattern(계속)  (0) 2006.10.05
2장 Observer Pattern  (0) 2006.10.05
1장 Strategy Pattern (끝)  (0) 2006.09.26
1장 Strategy Pattern(계속)  (2) 2006.09.26
1장 Strategy Pattern  (0) 2006.09.26
top


1장 Strategy Pattern

Design Pattern : 2006.09.26 00:17




위 다이어그램을 보면 Duck class를 상속을 이용하여 재사용 하고 있습니다.
필요한 부분( 여기서는 display() )만 overriding 해주면 되기 때문에 상당히 편리해 보입니다.
기본 기능으로 오리가 날수 있도록 하고 싶을 때...



위와 같이 상위 class에 추가하기만 하면 모든 하위 class들에 일일히 추가할 필요가 없기때문에 편리해 보입니다.
하지만...
날지 못하는 오리(고무 인형 오리)의 경우라면 상속 받지 말아야 할텐데.
특정 method를 제외하고 상속하는 방법 같은 것은 배운적이 없네요 :)
상속을 못하게 하는 방법은 있지만 그렇게 하면 다른 자식 class들은 어떻게 하나요? 하핫;
method하나가지고 뭘 그러나.. 그냥 method를 overring해서 안에서 아무것도 안하면 되지 않을까...라는 생각을 처음엔 했었습니다.
그러나...
그러한 method가 무진장 많다고 했을 때를 생각해 보면 코드 낭비에 시간 낭비라는 생각이 안들 수가 없습니다. 무언가 뾰족한 수가 필요합니다.

'Design Pattern' 카테고리의 다른 글

Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제(계속)  (0) 2006.10.08
Strategy Pattern 예제  (0) 2006.10.08
Head First Degisn Patterns 소스코드 다운받기.  (0) 2006.10.08
2장 Observer Pattern(끝)  (0) 2006.10.05
2장 Observer Pattern(계속)  (2) 2006.10.05
2장 Observer Pattern(계속)  (0) 2006.10.05
2장 Observer Pattern  (0) 2006.10.05
1장 Strategy Pattern (끝)  (0) 2006.09.26
1장 Strategy Pattern(계속)  (2) 2006.09.26
1장 Strategy Pattern  (0) 2006.09.26
top