Observer 패턴은 자바 프로그램에서 많이 사용되는 설계 패턴이다. 이 패턴은 동작 설계 패턴으로, 클래스가 느슨하게 연결되는 방식과 타 클래스 업데이트 시 하나의(또는 다수의) 클래스가 통지되는 방식을 정의한다. 기본적으로, 이는 특정 장소에서 무슨 일이 발생할 경우, 이를 보고있었거나 관심을 가지고 있던 사람들에게 상황을 통지하는 것을 의미한다.
Observer 패턴을 취급하는 방식에는 두 가지가 있는데, 첫 번째 방식은 java.util package에서 볼 수 있는 Observer
와 Observable
클래스를 수반하는 것이고, 두 번째 방식은 컴포넌트에 이벤트 리스너를 등록하는 JavaBeans 컴포넌트 모델을 따르는 것이다.
JavaBeans 이벤트 모델 생성에 앞서 Observer
와 Observable
클래스는 Observable 패턴의 구현을 기술한다. 달리 말해서 이 클래스들은 Java 플랫폼 1.0 버전 때부터 사용되어 왔고, 기술적으로 하자가 없었으며 여전히 라이브러리에 존재하고 있는 것이다. 또한, 이 클래스들은 여전히 Observable 패턴 구현에 사용할 수는 있지만, 두 번째 모델인 JavaBeans 컴포넌트 모델이 일반적으로 사용된다. Observable 패턴 구현을 위해 이 클래스들을 사용하는 데 따른 한 가지 중요한 문제는 Observable
확장이 필요하다는 점인데, 이 경우 자바 플랫폼의 단일 상속 세계에서는 불가능할 수도 있는 클래스 하이어라키 구조를 강요 받게 된다.
이벤트 리스너를 등록하는 JavaBeans 컴포넌트 모델은 일련의 add 및 remove 메소드를 수반하는데, 여기서 리스너 타입은 메소드 이름에 내장되어 있다. 예를 들어, 버튼의 선택을 관찰하기 위해서는 컴포넌트에 ActionListener
를 등록한다.
ActionListener listener = new ActionListener() {n public void actionPerformed(ActionEvent actionEvent) {n …n }n }; n JButton button = new JButton(“Pick Me”);n button.addActionListener(listener);n시스템 정의 클래스를 위한 Observer 패턴은 이것이 전부라고 할 수 있는데, 리스너 인터페이스를 구현하고, 그것을 관찰 Subject에 첨부한 다음 기다린다. Subject는 관찰되는 대상으로, 누가 관찰하고 있는지를 기억하는 일을 책임진다. JavaBeans 컴포넌트 모델의 경우,
Observer
객체를 첨부, 분리하기 위한 인터페이스로 add/remove 리스너 네이밍 패턴이 사용된다. Subject의 상태가 변경되면 이를 Observer
객체에 통지한다.
패턴의 주된 목표 중 하나는 Subject와 Observer
의 느슨한 연결을 가능케 하는 것이다. JButton
이 선택되면, ButtonNotification
이라 불리는 가상 서브클래스의 특정 메소드를 호출하는 대신 누구나 구현할 수 있는 인터페이스로 통지가 추상화된다. JButton
은 첨부된 Observer
(리스너)가 어떤 클래스인지 전혀 개의치 않는데, 실제로 버튼은 구현 클래스가 수정되더라도 오로지 Observer
가 리스너를 구현한다는 사실에만 관심을 가진다.n\u003cbr\>Observer 패턴 사용 시 주의할 필요가 있는 여러 가지 복잡한 문제들이 있다. 첫째는 메모리 누출의 가능성이다. \u003ccode\>Observer\u003c/code\>에 대한 레퍼런스는 Subject에 의해 관리되는데, Subject가 레퍼런스를 해제할 때까지는 garbage collector로 \u003ccode\>Observer\u003c/code\>를 제거할 수 없다. 이런 가능성에 유의하여 적절한 상황에서 \u003ccode\>Observer\u003c/code\>를 제거해야 한다. 아울러 (적어도 이벤트 리스너를 등록할 때는) 일련의 \u003ccode\>Observer\u003c/code\> 객체가 unordered collection에서 관리된다는 점에 주목할 것. 먼저 등록된 리스너가 먼저 통지되는지 마지막에 통지되는지를 반드시 알아야 할 필요는 없으나 반드시 객체 A가 먼저 통지되고 이어서 객체 B가 통지되는 cascading 방식의 통지가 필요한 경우에는 중간 객체를 도입하여 순서가 지켜지도록 해야한다. 단지 Observer를 특정 순서로 등록한다고 해서 반드시 그 순서에 따라 통지가 이루어지는 것은 아니다. \u003cbr\>\u003cbr\>Observer 패턴을 모델링하는 자바 플랫폼의 또 다른 영역으로는, guaranteed delivery, non-local distribution, persistence 등의 이점을 갖춘 JMS(Java Message Service)를 들 수 있다. JMS publish-subscribe 메시징 모델은 무한한 수의 가입자가 관심 있는 주제를 청취할 수 있게 해주는데, publish된 주제에 대한 메시지가 생성되면 모든 가입자들에게 내용이 통지된다. \u003cbr\>\u003cbr\>그 밖에도 자바 플랫폼에는 Observer 패턴을 모델링하는 여러 다른 분야가 있으며, 이 패턴은 자바 플랫폼 전반에 걸쳐 자주 사용된다. \u003cbr\>\u003cbr\>1995년\u003cem\>\u003ca style\u003d\”font-size:13px;color:rgb(153,153,204);font-family:Arial,Verdana,Helvetica,Sans-serif;text-decoration:none\” href\u003d\”http://www.amazon.com/exec/obidos/ASIN/0201633612/\” target\u003d\”_blank\” onclick\u003d\”retu top.js.OpenExtLink(window,event,this)\”\>설계 패턴(Design Pattes)\u003c/a\>이 출간된 이래로 이 패턴들에 대해 다양한 관점을 제시하고 추가 패턴을 소개하는 다른 책들이 발표된 바 있다. 그 중 다음 두 가지가 인기를 끌었다. \n\u003cul\>\n\u003cli\>\u003ca style\u003d\”font-size:13px;color:rgb(153,153,204);font-family:Arial,Verdana,Helvetica,Sans-serif;text-decoration:none\” href\u003d\”http://www.amazon.com/exec/obidos/ASIN/0596007124/\” target\u003d\”_blank\” onclick\u003d\”retu top.js.OpenExtLink(window,event,this)\”\>\u003cem\>Head First Design Pattes\u003c/em\>\u003c/a\> \n\u003cli\>\u003ca style\u003d\”font-size:13px;color:rgb(153,153,204);font-family:Arial,Verdana,Helvetica,Sans-serif;text-decoration:none\” href\u003d\”http://www.amazon.com/exec/obidos/ASIN/0321213351/\” target\u003d\”_blank\” onclick\u003d\”retu top.js.OpenExtLink(window,event,this)\”\>\u003cem\>Refactoring to Pattes\u003c/em\>\u003c/a\> \u003c/li\>\u003c/li\>\u003c/ul\>또한, 보다 심도 있는 설계 패턴에 관심이 있는 독자를 위해 \u003ca style\u003d\”font-size:13px;color:rgb(153,153,204);font-family:Arial,Verdana,Helvetica,Sans-serif;text-decoration:none\” href\u003d\”http://www.amazon.com/exec/obidos/ASIN/0321127420/\” target\u003d\”_blank\” onclick\u003d\”retu top.js.OpenExtLink(window,event,this)\”\>”,1]n);nn//–>n
Observer 패턴 사용 시 주의할 필요가 있는 여러 가지 복잡한 문제들이 있다. 첫째는 메모리 누출의 가능성이다. Observer
에 대한 레퍼런스는 Subject에 의해 관리되는데, Subject가 레퍼런스를 해제할 때까지는 garbage collector로 Observer
를 제거할 수 없다. 이런 가능성에 유의하여 적절한 상황에서 Observer
를 제거해야 한다. 아울러 (적어도 이벤트 리스너를 등록할 때는) 일련의 Observer
객체가 unordered collection에서 관리된다는 점에 주목할 것. 먼저 등록된 리스너가 먼저 통지되는지 마지막에 통지되는지를 반드시 알아야 할 필요는 없으나 반드시 객체 A가 먼저 통지되고 이어서 객체 B가 통지되는 cascading 방식의 통지가 필요한 경우에는 중간 객체를 도입하여 순서가 지켜지도록 해야한다. 단지 Observer를 특정 순서로 등록한다고 해서 반드시 그 순서에 따라 통지가 이루어지는 것은 아니다.
Observer 패턴을 모델링하는 자바 플랫폼의 또 다른 영역으로는, guaranteed delivery, non-local distribution, persistence 등의 이점을 갖춘 JMS(Java Message Service)를 들 수 있다. JMS publish-subscribe 메시징 모델은 무한한 수의 가입자가 관심 있는 주제를 청취할 수 있게 해주는데, publish된 주제에 대한 메시지가 생성되면 모든 가입자들에게 내용이 통지된다.
그 밖에도 자바 플랫폼에는 Observer 패턴을 모델링하는 여러 다른 분야가 있으며, 이 패턴은 자바 플랫폼 전반에 걸쳐 자주 사용된다.