헐리웃의 영화 관계자들 사이에서 격언처럼 사용되는 말이 있다고 합니다. 그것은 바로 "Don't call us, we'll call you." 인데요. 번역하면 "우리가 연락할테니 연락하지 마" 정도가 되겠죠.

눈치채셨겠지만 이 말이 그 바닥에서 유명하게 된 이유는, 바로 스타 지망생들의 전화공세 때문이라죠. 자신이 오디션에 합격했는지 확인하려는 지망생들의 전화 때문에, 관계자들이 업무를 볼 수 없을 정도가 되었던 것입니다. 그래서 생각해 낸 것이 바로, "네가 필요할 일이 있으면 우리가 연락할거야"라는 전략인 것이죠.


참으로 귀찮아 보이기까지 하는 이 짧은 말에는, 몇 가지 사전 조건이 포함되어 있습니다. 다음과 같은 조건들 말이죠.

- 영화 관계자는 지망생들의 목록을 관리하고 있다. (만난 적이 있다, 혹은 오디션을 본 적이 있다 등등)

- 영화 관계자에게는 지망생에게 연락해야 하는 특정 이유가 있다. (주연/조연/엑스트라/스텝 등 어떤 이유로든)

- 영화 관계자는 지망생의 연락처를 알고 있다. 혹은 연락할 수 있는 방법이 있다. (직접방문/전화/우편/지인을 통해 등등)


디자인 패턴 중 관찰자 패턴(Observer Pattern)은, 이 전략을 프로그래밍 영역으로 끌어온 것이라 할 수 있습니다. 개념적으로 간단하고 구현이 간편하기 때문에 수 많은 영역에서 이미 사용되고 있죠. 많은 프로그래밍 언어들이 언어 내에 관찰자 패턴의 기본적인 골격을 포함하고 있는 경우도 많이 있습니다.

그럼 이제, 관찰자 패턴에 대해 다룬 포스트 하나를 보면서 Java 프로그래밍 언어에서 관찰자 패턴이 어떻게 사용되고 어떻게 구현되는지 살펴보도록 하겠습니다. 


이 포스트의 원문 주소는 http://www.vogella.com/articles/DesignPatternObserver/article.html 입니다.


관찰자 패턴 (Observer Pattern)

1) 정의

관찰자 패턴은, 여러 객체 간의 일대다(one-to-many) 의존관계를 정의하는 디자인 패턴으로, 한 객체의 상태가 변경되었을 때 그 객체에 의존하고 있는 나머지 객체들이 변경 사항을 통보받고 자동적으로 어떤 동작을 수행하도록 하기 위해 사용됩니다.

여기서 관찰이 되는 객체를 대상(subject)이라 하고, 대상의 상태 변화를 주시하고 있는 객체를 관찰자(observer) 혹은 리스너(listener)라고 합니다.

 

2) 사용 예

관찰자 패턴은 Java 내에서 이미 흔하게 사용되고 있습니다. 예를 들어 사용자 인터페이스(UI)에서 사용되는 버튼(button)을 위해 리스너(listener)를 정의하는 것이 관찰자 패턴의 입니다. 버튼이 클릭되면 리스너가 그 내용을 통지받아 특정 동작을 수행하게 됩니다.

하지만 관찰자 패턴이 사용자 인터페이스 컴퍼넌트에서만 사용될 수 있는 것은 아닙니다.

예를 들어 어플리케이션 내에 현재 온도를 표시해주는 partA라고 하는 부분이 있다고 가정해봅시다. 그리고 partB는 현재 온도가 20도가 넘으면 녹색 불빛을 표시하기로 했다고 하면, partA의 상태 변화를 감지하기 위해 partBpartA에 자기 자신을 리스너로 등록해야 할 것입니다.

partA에서 기온이 변경되면 이벤트가 발생(trigger)될 것입니다. 그리고 이 이벤트는 등록되어 있는 모든 리스너들에게 전달될 것인데, 위의 경우에서는 partB가 전달을 받습니다. 이제 partB는 이벤트와 같이 전달된 정보를 얻어 화면을 갱신할 것입니다.

다음은 버튼에 리스너를 설정하는 예제 코드입니다.


Button button = new Button(shell, SWT.PUSH); 
button.addSelectionListener(new SelectionAdapter() {   
    @Override   
    public void widgetSelected(SelectionEvent e) {     
        // Handle the selection event         
        System.out.println("Called!");
    } 
}); 


3) 예제 코드

다음 예제는 Person 객체 내의 List 정보의 변경을 확인하는 관찰자를 만들 것입니다. 이를 위해 com.vogella.java.designpattern.observer.MyObserver 클래스와 그 외의 몇 가지의 클래스들을 이용할 것입니다.


package com.vogella.java.designpattern.observer;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

public class MyModel {

    private List persons = new ArrayList();
    private List listeners = 
            new ArrayList();

    public class Person {

        private String firstName;

        private String lastName;

        public Person(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public String getFirstName() {

            return firstName;
        }

        public void setFirstName(String firstName) {
            notifyListeners(this, "firstName", 
                    firstName, 
                    this.firstName = firstName);
            
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String lastName) {
            notifyListeners(this, "lastName", 
                    lastName, 
                    this.lastName = lastName);
        }
    }

    public List getPersons() {
        return persons;
    }

    public MyModel() {
        // Just for testing we hard-code the persons here:
        persons.add(new Person("Lars", "Vogel"));
        persons.add(new Person("Jim", "Knopf"));
    }

    private void notifyListeners(Object object, 
            String property, String oldValue, String newValue) {
        for (PropertyChangeListener listener : listeners) {
            listener.propertyChange(new PropertyChangeEvent(this, 
                            property, 
                            oldValue, 
                            newValue));
        }
    }

    public void addChangeListener(PropertyChangeListener newListener) {
        listeners.add(newListener);
    }
} 


package com.vogella.java.designpattern.observer;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

public class MyObserver implements PropertyChangeListener {
    public MyObserver(MyModel model) {
        model.addChangeListener(this);
    }

    @Override
    public void propertyChange(PropertyChangeEvent event) {
        System.out.println("Changed property: " + event.getPropertyName() + " old:"
                + event.getOldValue() + " new: " + event.getNewValue());
    }
}


package com.vogella.java.designpattern.observer;

import com.vogella.java.designpattern.observer.MyModel.Person;

public class Main {


  public static void main(String[] args) {
    MyModel model = new MyModel();
    MyObserver observer = new MyObserver(model);
    // We change the last name of the person, observer will get notified
    for (Person person : model.getPersons()) {
        person.setLastName(person.getLastName() + "1");
    }
    // We change the  name of the person, observer will get notified
    for (Person person : model.getPersons()) {
        person.setFirstName(person.getFirstName() + "1");
    }
  }
}


4) 평가

관찰자 패턴은 객체 지향 프로그래밍의 원칙 중 하나인 OCP(Open Closed Principle)을 가능케 합니다. 이 원칙은, 클래스들은 확장에는 열려(Open)있어야 하나 변경에는 닫혀(Closed) 있어야 함을 의미합니다.

관찰자 패턴을 이용하면, 대상(subject)은 관찰자를 숫자에 제한 없이 등록할 수 있게 됩니다. 새로운 리스너가 대상 객체를 관찰하려 한다 하더라도 대상 클래스의 코드에는 아무런 변경도 필요하지 않습니다.

, 관찰자 패턴은 대상 클래스를 관찰자 클래스로부터 분리(decouple)하도록 해 줍니다. 관찰자만이 대상 클래스의 존재를 인식할 뿐입니다.



아래는 관찰자 패턴의 UML 입니다.위의 내용을 잘 이해했다면 UML에 익숙하지 않은 분이라 하더라도 쉽게 이해가 되시리가 생각합니다. 위에서 이미 설명된 내용을 그저 UML로 표기한 것 뿐이니(UML이란 원래 그런 겁니다.) 더 이상의 자세한 설명은 생략하....


UML of Observer Design Pattern (출처 : Wikipedia)



지금까지 관찰자 패턴에 대해 간략하게 알아보았습니다. 

위 포스트에서 얼핏 소개가 된 내용이 있는데요, 객체 지향 프로그래밍의 원칙에는 크게 다섯 가지 원칙이 있습니다. 이른바, [SOLID principles] 라고 불리는 것인데요, 나중에 기회가 된다면 이에 대해 다뤄 보도록 하겠습니다.


여기까지 보신 분들 중, EDA라고 불리는 Event Driven Architecture와 관찰자 패턴은 어떻게 다른가 하는 의문이 드신 분들이 있을 것입니다. 실제로 특정 이벤트에 대한 처리를 위해 관찰자 패턴을 이용하여 구현한 경우가 많기에, 많은 개발자들이 이러한 질문을 해 오고 있습니다. 


과연 관찰자 패턴과 EDA는 완전히 같은 것일까요? 엇비슷한 것일까요? 아니면 혹시 포함 관계에 있는 것일까요? 이에 대한 내용은 다음에 EDA에 대해 다루면서 다시 한 번 살펴보도록 하겠습니다. 성격이 급한 분이라면, [Observer Pattern vs Event Driven Architecture]로 구글링하여 먼저 확인해 보실 수 있겠죠?

신고
Posted by Layered 트랙백 0 : 댓글 0

댓글을 달아 주세요


티스토리 툴바