[App 개발] Cocoa Design Patterns (5)
본문
GOF의 패턴에 익숙하신 분들은 아마 타겟/액션이 마치 커맨드 패턴의 구현이라고 생각될 것입니다. 그러나 커맨드 패턴같은 것이 타겟/액션과 같은 구현이 이용된다 하더라도 Objective-C에서는 그것이 필요가 없습니다. 커맨드 패턴은 정적인 객체 지향 언어에 결여되어 있는 동적인 요소들을 만들어내기 위하여 더 많이 사용됩니다. 정적인 언어에서는 한 번도 본 적이 없는 객체의 메세지 전달은 일반적으로는 불가능합니다. 이것을 구현하기 위해서는 여러분은 invoke와 같은 가상 메쏘드를 구현하고 있는 커맨드라고 하는 추상적 슈퍼클래스를 만들어야 합니다. 그리고 전달하고자 하는 모든 메쏘드들을 위한 서브클래스를 만들어 줍니다. 마지막으로, 전달자는 커맨드 서브클래스의 어떤 인스턴스를 가지고 메세지를 전달하기 위하여 그 객체에 있는 invoke를 호출합니다. 이렇게 함으로써 전달자 클래스가 컴파일된 상태에서 보내어지는 메세지가 어떤 것인지는 몰라도 전달자 객체가 다른 객체에게 메세지를 전달할 수 있습니다.
왜냐하면 Objective-C는 아주 동적인 언어이기 때문에 어떤 메세지를 전달하기 위하여 위의 모든 과정을 거쳐야 할 필요가 없습니다. 그 대신 전달하는 객체에게 셀렉터가 전달되어 어떠한 메세지를 전달할 것인지를 결정하게 됩니다. 그러면 전달자는 -performSelector: 메쏘드나 필요한 경우 -performSelector:withObject와 같은 변형 메쏘드를 메세지를 발생시키기 위하여 사용합니다.
셀렉터는 전달될 메세지를 결정할 뿐 메세지를 수신하지는 않습니다. 어떤 경우에는 필요하기도 하지만 언제나 그렇지는 않습니다. 만약 여러분이 메세지와 수신기를 한 객체 안에 갖기를 원한다면 NSInvocation을 사용할 수 있습니다. NSInvocation은 메세지, 수신기, 그리고 메세지에 필요한 인수들을 포함하고 있습니다. NSInvocation 클래스가 코코아에서 GOF의 Command 패턴과 가장 가까운 클래스입니다.
Delegates
새로 코코아 개발자가 되신 분들이 하는 가장 초보적인 실수는 불필요한 코코아 객체의 서브클래스를 만드는 것입니다. 일반적으로 객체의 동작을 바꾸려고 하는 목적으로 서브클래스를 만듭니다. 다른 대부분 객체지향 응용 프로그램 프레임웍에서는 서브클래스가 클래스의 동작을 변경시키는 유일한 방법입니다. 그러나 코코아에서는 서브클래스 기법을 대신하여 위임(delegation)이라는 개념을 도입했습니다. GOF 패턴 중에서는 위임 개념을 정확히 설명하는 것은 없습니다. 위임이라는 것은 옵저버와 GOF 의 Chain of Responsibility 패턴의 혼합이라고 할 수 있습니다.
위임은 프레임웍 개발자가 설계시 선택해야 할 일을 잠시 미루어둘 수 있는 한 가지 방법입니다. 오로지 한 가지 방법으로 모든 것을 다 처리하는 대신 많은 코코아 클래스들은 특정한 상황에서 다른 객체에게 어떤 작업을 할 수 있도록 만들 수 있습니다.
예를 들어, 사용자가 윈도우 타이틀 바에 있는 닫기 버튼을 눌렀을 때의 기본적인 행동은 윈도우를 단는 일입니다. 그러나 만일 윈도우에 변경된 문서가 있어서 응용 프로그램이 윈도우를 닫기 전에 변경된 사항을 저장해야 할지를 사용자에게 묻는 기능을 만들어야 한다면 어떻게 할까요? 코코아에서는 윈도우는 다른 객체에게 "지금 닫을 건데, 괜찮냐?"고 물어보게 됩니다. 객체는 아마 화면에 문서를 저장할 것인지 윈도우 닫기를 취소할 것인지를 선택하는 상자가 열려서 사용자의 의향을 묻고 난 다음 yes나 no로 대답하게 될 것입니다. 윈도우의 동작을 변경하기 위해서 서브클래스를 만들어야 할 필요는 없습니다. 그 대신 응용 프로그램이나 컨텍스트 고유의 방법으로 질문에 대답할 수 있도록 만들어진 다른 객체가 제공됩니다.
이 결정에 참여하게 되는 다른 객체가 바로 대리인(delegate)입니다. 객체로부터 대리인에게 전달되는 메세지들이 대리인 메세지입니다. 대리인에게 메세지를 보내는 객체에는 적당한 용어가 없기 때문에 이 책에서는 이러한 객체를 구별하기 위하여 위임자(delegator)라는 이름으로 쓰겠습니다. 일반적으로 위임자 클래스의 문서와 헤더에는 대리인에게 전달될 수 있는 메세지들에 대해서 기술되어 있습니다.
NSApplication, NSWindow, NSTableView, NSToolBar와 같은 대부분의 복잡한 응용 프로그램 킷 클래스들 은 모두 위임자입니다.
대리인에게 전달되는 어떤 메세지들은 대리인으로부터의 회신이 필요하지 않고 어떤 이벤트가 실행되기 전후에 어떤 작업을 대리인으로 하여금 수행하도록 합니다. 예를 들어, 대리인은 윈도우가 화면에 놓여지기 바로 직전이나 직후에 메세지를 받을 수 있습니다. 이렇게 해서 대리인은 적당한 시간에 특별한 초기화나 다른 작업을 수행할 수 있는 기회를 가지게 됩니다.
대리인은 모든 대리인 메세지를 구현해야 할 필요는 없습니다. 단지 필요한 메세지만을 구현하면 됩니다. 위임자는 특정 메세지를 보내기 전에 대리인이 메세지에 반응하는지를 항상 확인해야 합니다. 그 메세지에 대리인이 반응하지 않으면 보내지 않으면 됩니다.
Note
메세지를 보내기 전에 대리인이 메세지에 반응하는지를 검사하는 것은 자칫 비효율적으로 보일 것입니다. 그러나 코코아의 실제 구현은 꽤 영리하게 되어 있습니다. 대리인이 설정되었을 때 코코아는 대리인이 처리할 수 있는 메세지를 확인하고 대리인 메세지를 보낼 때 사용하기 위하여 캐시에 저장하게 됩니다.
대리인의 한 가지 제한사항은 어떤 특정한 대리인 메세지들만이 위임자에게 알려져 있다는 사실입니다. 만약 위임자를 만드는 사람이 여러분이 받거나 전달하고자 하는 어떤 메세지에 대하여 대리인 메세지가 보내어지지 않는다면 대리인은 동작하지 않을 것입니다. 그런 경우에는 객체의 서브클래스만이 유일한 해결방법일 것입니다. 다행스럽게도 코코아에서 서브클래스가 필요한 경우는 많지 않습니다. 이미 존재하고 있는 대리자 메세지는 여러분이 원하는 거의 대부분의 기능을 포함할 수 있을 만큼 풍부하게 제공되어 있습니다.
대리인의 또 다른 제한점은 객체는 일반적으로 단 하나의 대리인만을 가진다는 점입니다. 거기에는 다른 방법이 없습니다. 예를 들어, NSApplication 인스턴스는 여러 개의 대리인을 가져야 합니다. 만약 하나의 위임자로부터 여러 개의 대리인들이 메세지를 받게 하려면 대리인이 메세지를 다른 대리인에게 전달하도록 만들어 줍니다.
"윈도우를 닫을까요?" 같은 응답이 필요한 메세지의 경우 그 메세지를 다른 객체로 포워딩하는 것이 유일한 방법입니다. 한편 다른 대리인들이 이벤트에 대한 통지만을 요구할 경우에는 Notification 패턴이 다중 대리인 문제를 해결하는 방법으로 사용될 수 있습니다.
최신글이 없습니다.
최신글이 없습니다.
댓글목록 0