노무현 대통령 배너

Observer Pattern 옵저버 패턴의 수정 – 옵저버는 주제를 몰라요.

by on 5.20, 2009, under Design Pattern

the_observer_2이 포스트는 Head First Design Pattern : Observer Pattern 옵저버 패턴을 액션스크립트로 컨버팅 의 마지막 부분에서 언급했던 잘못된 패턴 구현에 대한 코드 수정을 위한 포스트 입니다.

이 문제의 발단은 옵저버 구상 클래스에서 주제인 weatherData 객체를 레퍼런스로 저장하는데서 비롯되었습니다. 주제가 어떤 녀석인지 옵저버에 저장하는 순간 이 옵저버는 더이상 옵저버가 아니고 주제에 직접적으로 관여하는 입장이 되어버립니다.

아래 코드 부분은 수정된 옵저버 구상 클래스 입니다. 현재 주석처리 되어있는 생성자 부분에서 주제인 weatherData 를 인스턴스 변수로 저장할 뿐만 아니라, 심지어 옵저버 스스로 옵저버가 되기를 희망하며 주제의 메소드를 직접 호출하며 옵저버 등록을 시도하게 되어버렸던 것입니다. 이 결과, 주제는 info를 옵저버 들에게 돌려야 하므로 옵저버들이 누군지 당연히 원래부터 알고 있고[01] 옵저버 역시 주제가 누군지 알고 있을 뿐더러 주제의 메소드를 호출하는 형태를 띄게 되면서, 객체지향 언어에서 지양(止揚)해야 할, 객체간 강한 결합을 해버리게 됩니다.[02] 

0
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
package
{
	public class CurrentConditionsDisplay implements IObserver, IDisplayElement
	{
		private var temperature:Number;
		private var humidity:Number;
		//주제를 저장하는 인스턴스변수 삭제
		//private var weatherData:ISubject;
 
		//생성자 메서드에 있던 $weatherData:ISubject 주제를 받는 인자 삭제
		public function CurrentConditionsDisplay ()
		{
			//생성자에서 옵저버역할에 대해서는 할일 없음. 모두 삭제
			//this.weatherData = $weatherData;
			//weatherData.registerObserver( this )
		}
 
		public function update( $temperature:Number, $humidity:Number, $pressure:Number ):void
		{
			this.temperature = $temperature;
			this.humidity = $humidity;
			display();
		}
 
		public function display():void
		{
			trace( "현재 온도 :", temperature, "도 / 습도 :", humidity )
		}
	}
}

이를 해결하고자 위의 수정본에서 보는바와 같이 옵저버 구상 클래스 생성자 주변에 있던 주제 관련 코드를 모두 없앴습니다.

그럼 호스트 코드는 어떻게 변해야 하는지 보도록 할까요?

0
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
31
package
{
	import flash.display.Sprite;
 
	public class Main extends Sprite
	{
		public function Main()
		{
			//주제 객체를 생성
			var weatherData:WeatherData = new WeatherData();
 
			//디스플레이를(옵저버) 객체를 생성
			var currentDisplay1:CurrentConditionsDisplay = new CurrentConditionsDisplay();
			var currentDisplay2:CurrentConditionsDisplay = new CurrentConditionsDisplay();
			var currentDisplay3:CurrentConditionsDisplay = new CurrentConditionsDisplay();
 
			//이렇게 주제가 옵저버를 등록하게 하면 옵저버는 주제를 몰라도 되겠죠.
			weatherData.registerObserver( currentDisplay1 );
			weatherData.registerObserver( currentDisplay2 );
			weatherData.registerObserver( currentDisplay3 );
 
			weatherData.setMeasurement( 20, 65, 30.4 ); // 1,2,3 의 디스플레이가 출력
				//출력 : 현재 온도 : 20 도 / 습도 : 65
				//출력 : 현재 온도 : 20 도 / 습도 : 65
				//출력 : 현재 온도 : 20 도 / 습도 : 65
			weatherData.removeObserver( currentDisplay1 ); // 1번을 빼면
			weatherData.setMeasurement( 28, 90, 29.2 ); // 2,3 의 디스플레이가 출력
				//출력 : 현재 온도 : 28 도 / 습도 : 90
				//출력 : 현재 온도 : 28 도 / 습도 : 90
		}
	}
}

수정되기 전의 호스트코드와 마찬가지로 주제 객체(날씨 데이터)를 생성하고, 옵저버(디스플레이)를 필요한 수만큼 생성하였습니다. 그러나 이제 디스플레이를 new 로 생성하면서 생성자에 주제를 던져주지 않죠. 주제에 대한 옵저버 등록은 호스트코드에서 직접 합니다. 그리고 나머지 사용 방법은 이전과 다르지 않습니다.

호스트코드에서 해야 할 일이 약간 늘어났지만, 옵저버가 주제를 전혀 몰라도 된다는 점에서 얻어지는 이득이 훨씬 많습니다. 만약 옵저버에 대한 추가요건이나 버그픽스 요청이 접수 되었다면 주제와의 관계는 전혀 신경쓰지 않고 옵저버 클래스 자체에 집중하여 작업을 할 수 있게 되는 것이죠.

이 글을 복사해서 퍼가시는건 허용하지 않습니다. 글의 주소를 다른곳에 알려주시는 것은 환영합니다.
  1. 주제 객체 내부에 배열로 옵저버 리스트를 관리하고 있었습니다. []
  2. OOP 의 원칙 중 클래스 사이의 결합도는 약하게, 하나의 클래스 안에서의 응집도는 강하게 라는 원칙이 있음은 주지의 사실입니다. []

관련된 글

:, , , , , , , , , , , ,

10 Comments for this entry

  • utimeNo Gravatar

    이 부분은 저도 동감합니다.
    저도 책보면서 이건 아니다 싶어 Observer에서 Subject 빼고 구현했었죠~

    잘 보고 가요~

  • 세계의끝No Gravatar

    네 종종 놀러오세요.

  • 닥서클No Gravatar

    역시 많이 공부해야겠네요.
    저라면 그냥 지나첬을법하네요.

    감사합니다^^

  • 김갑영No Gravatar

    좋은 패턴 정보 잘 읽고 있습니다. 공부하는데 너무 도움이 되네요 감사합니다.^^

  • 이상태No Gravatar

    좋은 글 잘 읽었습니다. PureMVC 생각이 나네요^^

  • 미친바람No Gravatar

    때로는 subject객체를 view객체에서 가지고 있어서 좋을때도 있습니다.

    일예로 겨울잠을 자는 개구리가 옵저버가 된다고 가정합니다.
    일정 온도 이상으로 올라가면
    개구리는 subject객체에게 탈퇴한다고 알리고
    겨울잠을 깨도록 한다면 되겠죠.
    이건 view 객체의 용도에 맞게 설정하면 되지 않을까 싶네요.

    감사합니다. 덕분에 디자인 패턴이 뭔지 잘 공부하고 있습니다. 혼자 삽질하다가 큰 도움을 받고 있습니다.

    • 세계의끝No Gravatar

      본문에도 썼지만 subject 객체 참조를 view 에서 가지고 있는 순간부터 그것은 옵저버 패턴이라 하지 않습니다. 그저 객체간 통신을 하고 있다고 표현하는 거죠.
      옵저버 패턴의 장점을 포기하지 않으려면 개구리가 subject 에서 탈퇴시키는것을 개구리 자신이 하는것 보다는 호스트 코드에서 하는게 좋습니다.

Leave a Reply

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Meta