[Cocoa Design pattern] 23. Decorator

**데코레이터란?**
– 서브클래싱을 통해 기능을 추가하는 대신 컴포지션을 통해서 공통적으로 재사용 가능한 기능을 객체에 추가
– 서브 클래싱은 컴파일 단계에서 정의해야 하지만, 데코레이터는 런타임 단계에서 추가 및 구성 가능함.
ex) NSScrollView
**패턴이 만들어진 동기 **
– 기존 객체에 여러가지 기능을 추가하고 싶음. 그러나, 클래스 수의 증가가 문제임.
– 서브 클래스 = is – a 관계
Text – RulerText – BorderedRulerText
– 상속을 통해서 필요한 기능을 확장해 나가는 형태, 특정 기능을 위해 계층이 복잡해짐.
– 다중 상속을 통해서 간단한 계층을 시도하지만,
다중상속은 클래스의 수를 줄이는것 보다는 상속 관계를 바꿔줌.
**데코레이터 패턴의 목표 **
1. 상속 대신 조합으로 어플리케이션의 동작을 사용자화 한다.
2. 런타임의 유연성 제공, 런타임 상태에서 기능을 동적으로 추가 및 제거 가능
3. 클래스 대신 각각의 인스턴스에 기능을 추가한다.
4. 필요한 클래스의 수를 줄여준다.
**패턴으로 문제 해결**
– 조합(Composition)은 Has – a 관계를 정의한다. 데코레이터 패턴은 암묵적으로 has-a 관계를 사용한다.
ex)
NSClipView 인스턴스가 자신의 도큐먼트 뷰를 데코레이트한다.
= NSClipVIew 인스턴스가 도큐먼트 뷰를 소유한다
– 조합은 런타임시에 구성되고, 동적으로 바꿀수 있다
*** NSScrollView
**– setDocumentView 메소드를 제공해서 내장된 클립뷰의 도큐먼트 뷰를 설정하도록 제공
– 도큐먼트 뷰는 NSView의 서브클래스라면 가능 즉, 사용자 정의의 커스텀 뷰도 가능하며, 숫자 제한이 없다.
**코코아 사용 예제 **
일반 적인 데코레이터 패턴의 사용 예제 : [http://mrhook.co.kr/79](http://mrhook.co.kr/79)
– 이 패턴은 주로 MVC의 뷰 단계 에서만 주로 사용된다. – 예외도 있다.
**NSAttributedString
**– NSString + (폰트, 문단 스타일, 이미지 내장 등등) : 속성을 데코레이트
– 자신이 꾸미는 문자열을 수정하지 않는다. 단지, 그 문자열과 추가 정보만을 함께 저장함.
*365p. 표23.1 중요한 코코아 데코레이터 클래스 *
**액세서리 뷰 **
– 코코아 표준 사용자 인터페이스 패널 : 사용자가 만든 데코레이터 추가 가능하다.
**NSSavePanel, NSColorPanel 등등**
**–** setAccessoryView 메소드 제공 : 해당 패널에 원하는 액세서리뷰를 표시 할수 있음.
– 표준 패널은 다양한 패널 클래스를 서브 클래싱 하지 않아도 기능을 추가 할 수 있다
*** OS X 10.5 부터 NSPrintPanel과 NSPageLayout 클래스에 addAccessoryContoller 메서드로 액세서리뷰를 관리 하는 새로운 방식 제공함. **
– 액세서리 뷰를 직접 사용하는 것에서 액세서리 뷰 컨트롤러를 사용하게 변화
– MVC 패턴의 일관된 사용을 장려, 액세서리 뷰와 어플리케이션 로직 사이에 위치한 컨트롤러 코드를 어디에 구현해야 하는지 명확히 함.
**
패턴 사용 결과 **
– 객체지향의 상속관계는 강력 그러나, 의존성의 원인임.
– 컴파일시 정적으로 설정되고, 서브클래스의 모든 인스턴스에 영향을 준다.
– 컴포지션은 보다 유연한 대안을 제공함.
– 객체를 런타임시 확장하는것은 더 동적이고, 클래스가 아닌 인스턴스 단우에서의 적용이 가능하다.
– 다수의 클래스 사용을 하지 않고도 더 컴포지션으로 다수의 기능을 추가하는 것이 가능하다.
– 다른 프레임 워크 에서는 데코레이터가 꾸미는 객체와 동일한 인터페이스를 갖도록 요구함.
– 코코아에서는 제약이 없음.