책임 체인 패턴

Chain-of-responsibility pattern

객체 지향 설계에서 책임의 사슬 패턴명령 객체의 출처와 일련의 처리 객체로 구성된 행동 설계 패턴이다.[1]각 처리 객체는 처리할 수 있는 명령 객체의 유형을 정의하는 논리를 포함하고 있으며, 나머지는 체인의 다음 처리 객체로 전달된다.또한 이 체인의 끝에 새로운 처리 객체를 추가하는 메커니즘이 존재한다.

표준 책임 체인 모델의 변화에서, 일부 핸들러는 다양한 방향으로 명령을 전송하여 책임의 트리를 형성할 수 있는 분산 처리자 역할을 할 수 있다.경우에 따라 이러한 현상이 반복적으로 발생할 수 있으며, 처리 객체가 문제의 일부 작은 부분을 해결하려는 명령을 사용하여 상위 처리 객체를 호출할 수 있다. 이 경우 명령이 처리될 때까지 재귀가 계속되거나 트리 전체가 탐색될 때까지 반복된다.XML 통역사는 이런 방식으로 작동할 수 있다.

이 패턴은 느슨한 커플링의 생각을 촉진시킨다.

책임 체인 패턴은 구조적으로 장식자 패턴과 거의 동일하며, 다른 점은 장식가의 경우 모든 계층이 요청을 처리하는 반면, 책임 체인의 경우 체인 내 클래스 중 정확히 하나가 요청을 처리한다는 것이다.이것은 GoF 책의 책임 개념에 대한 엄격한 정의다.그러나 많은 구현(아래 로거 또는 UI 이벤트 처리 또는 자바에서의 서블릿 필터 등)을 통해 체인의 여러 요소가 책임을 질 수 있다.

개요

책임의 사슬 설계[2] 패턴은 유연하고 재사용 가능한 객체 지향 소프트웨어(즉, 구현, 변경, 테스트 및 재사용하기 쉬운 객체)를 설계할 때 반복적인 설계 문제에 대한 일반적인 해결책을 설명하는 23개의 잘 알려진 GoF 설계 패턴 중 하나이다.

책임의 사슬 설계 패턴이 해결할 수 있는 문제는 무엇인가?

[3]

  • 요청의 송신자를 수신기에 연결하지 않아야 한다.
  • 둘 이상의 수신자가 요청을 처리할 수 있어야 한다.

요청을 전송하는 클래스 내에서 직접 요청을 구현하는 것은 클래스를 특정 수신기에 결합시키고 여러 수신기를 지원할 수 없게 하기 때문에 융통성이 없다.

책임 체인 설계 패턴은 어떤 솔루션을 설명하고 있는가?

  • 런타임 조건에 따라 요청을 처리하거나 체인 상의 다음 수신자에게 전달할 책임이 있는 수신기 개체의 체인을 정의하십시오(있는 경우).

이것은 우리가 어떤 사람이 요청을 처리하는지 알 필요 없이 일련의 수신자에게 요청을 보낼 수 있게 해준다.요청은 수신자가 요청을 처리할 때까지 체인을 따라 전달된다.요청의 송신자는 더 이상 특정 수신기에 연결되지 않는다.

아래 UML 클래스 및 시퀀스 다이어그램을 참조하십시오.

구조

UML 클래스 및 시퀀스 다이어그램

책임 체인 설계 패턴에 대한 샘플 UML 클래스 및 시퀀스 다이어그램.[4]

위의 UML클래스 다이어그램에서Sender클래스는 특정 수신기 클래스를 직접 지칭하지 않는다.대신,Sender에 언급하다Handler요청 처리를 위한 인터페이스(handler.handleRequest()() 이므로 다음과 같다.Sender요청을 처리하는 수신자와는 무관하게.Receiver1,Receiver2그리고Receiver3계급이 실행하다.Handler요청을 처리하거나 전달하여 인터페이스(런타임 조건에 따라 다름)
UMLsequence 다이어그램은 런타임 교호작용을 보여준다.이 예에서는 다음과 같이 한다.Sender반대 전화handleRequest()에서receiver1목적어(유형)Handler. The.receiver1요청을 에 전달하다.receiver2에 대한 요청을 다시 전달한다.receiver3는 요청을 처리(처리)

자바 예제

아래는 자바에서 이러한 패턴의 예다.로거는 각각 다른 로그 레벨로 구성된 로거 체인을 사용하여 생성된다.

수입하다 java.util.배열; 수입하다 java.util.EnumSet; 수입하다 java.util.function.소비자;  @기능적인터페이스 공중의 접점 로거 {     공중의 열거하다 로그 수준 {         정보, 디버그, 경고, 오류, 기능_메시지, 기능_오류;          공중의 정태의 로그 수준[] 전부() {             돌아오다 가치();         }     }      추상적 공허하게 하다 메세지( 음스그, 로그 수준 엄격함);      체납 로거 추가다음(로거 nextLogger) {         돌아오다 (음스그, 엄격함) -> {             메세지(음스그, 엄격함);             nextLogger.메세지(음스그, 엄격함);         };     }      정태의 로거 writeLogger(로그 수준[] 레벨, 소비자<> 문자열소비자) {         EnumSet<로그 수준> 세트 = EnumSet.카피오프(배열.AsList(레벨));         돌아오다 (음스그, 엄격함) -> {             만일 (세트.포함하다(엄격함)) {                 문자열소비자.받아들이다(음스그);             }         };     }      정태의 로거 콘솔로거(로그 수준... 레벨) {         돌아오다 writeLogger(레벨, 음스그 -> 시스템.잘못을 저지르다.인쇄하다("위로를 위한 쓰기: " + 음스그));     }      정태의 로거 e-메일 로거(로그 수준... 레벨) {         돌아오다 writeLogger(레벨, 음스그 -> 시스템.잘못을 저지르다.인쇄하다("메일을 통해 전송:" + 음스그));     }      정태의 로거 fileLogger(로그 수준... 레벨) {         돌아오다 writeLogger(레벨, 음스그 -> 시스템.잘못을 저지르다.인쇄하다("로그 파일에 쓰기: " + 음스그));     } }  계급 러너 {     공중의 정태의 공허하게 하다 본래의([] 아그) {         // 불변의 책임 사슬 구축         로거 노상강 = 콘솔로거(로그 수준.전부())                 .추가다음(e-메일 로거(로그 수준.기능_메시지, 로그 수준.기능_오류))                 .추가다음(fileLogger(로그 수준.경고, 로그 수준.오류));          // 콘솔에 모든 로그 레벨이 있으므로 콘솔 로거로 처리         노상강.메세지("입력 기능 ProcessOrder().", 로그 수준.디버그);         노상강.메세지("주문기록 회수", 로그 수준.정보);          // e-메일 로거가 Functional_Error & Functional_Message를 구현하므로 콘솔 로거 및 e-메일 로거로 처리됨         노상강.메세지("고객 C1을 위해 D1일자 주문 ORD1을 처리할 수 없음.", 로그 수준.기능_오류);         노상강.메세지("발송주문.", 로그 수준.기능_메시지);          // fileLogger가 경고 및 오류를 구현하므로 콘솔 로거 및 fileLogger로 처리됨         노상강.메세지("Branch DataBase에 고객 주소 세부 정보가 누락됨.", 로그 수준.경고);         노상강.메세지("Organization DataBase에 고객 주소 세부 정보가 누락됨.", 로그 수준.오류);     } } 

C# 예제

이 C# 예제는 로거 애플리케이션을 사용하여 로그 수준에 따라 다른 소스를 선택한다.

네임스페이스 체인오프책임성;  [플랙스] 공중의 열거하다 로그 수준 {     없음 = 0,                 //        0     정보 = 1,                 //        1     디버그 = 2,                //       10     경고 = 4,              //      100     오류 = 8,                //     1000     FunctionalMessage = 16,   //    10000     FunctionalError = 32,     //   100000     전부 = 63                  //   111111 }  /// <<summary>> /// 책임 패턴 체인의 추상 핸들러. /// </> 공중의 추상적 계급 로거 {     보호의 로그 수준 로그마스크;      // 체인의 다음 핸들러     보호의 로거 다음에;      공중의 로거(로그 수준 가면을 쓰다)     {         .로그마스크 = 가면을 쓰다;     }      /// <<summary>>     /// Next logger를 설정하여 핸들러 목록/체인을 만드십시오.     /// </>     공중의 로거 SetNext(로거 넥스트로그인)     {         로거 마지막 로거 = ;          하는 동안에 (마지막 로거.다음에 != 무효의)         {             마지막 로거 = 마지막 로거.다음에;         }          마지막 로거.다음에 = 넥스트로그인;         돌아오다 ;     }      공중의 공허하게 하다 메시지(끈을 매다 음스그, 로그 수준 엄격함)     {         만일 ((엄격함 & 로그마스크) != 0) // logMask 비트가 심각도로 설정된 경우에만 True         {             WriteMessage(음스그);         }         만일 (다음에 != 무효의)          {             다음에.메시지(음스그, 엄격함);          }     }      추상적 보호의 공허하게 하다 WriteMessage(끈을 매다 음스그); }  공중의 계급 콘솔로거 : 로거 {     공중의 콘솔로거(로그 수준 가면을 쓰다)         : 밑의(가면을 쓰다)     { }      보호의 무효로 하다 공허하게 하다 WriteMessage(끈을 매다 음스그)     {         콘솔.WriteLine("위로를 위한 쓰기: " + 음스그);     } }  공중의 계급 EmailLogger : 로거 {     공중의 EmailLogger(로그 수준 가면을 쓰다)         : 밑의(가면을 쓰다)     { }      보호의 무효로 하다 공허하게 하다 WriteMessage(끈을 매다 음스그)     {         // 메일 송신 논리를 위한 자리 표시자, 일반적으로 전자 메일 구성은 구성 파일에 저장된다.         콘솔.WriteLine("메일을 통해 전송:" + 음스그);     } }  계급 파일 로거 : 로거 {     공중의 파일 로거(로그 수준 가면을 쓰다)         : 밑의(가면을 쓰다)     { }      보호의 무효로 하다 공허하게 하다 WriteMessage(끈을 매다 음스그)     {         // 파일 쓰기 로직의 자리 표시자         콘솔.WriteLine("로그 파일에 쓰기: " + 음스그);     } }  공중의 계급 프로그램 {     공중의 정태의 공허하게 하다 메인(끈을 매다[] 아그)     {         // 책임 체인 구축         로거 노상강;         노상강 = 새로운 콘솔로거(로그 수준.전부)                          .SetNext(새로운 EmailLogger(로그 수준.FunctionalMessage   로그 수준.FunctionalError))                          .SetNext(새로운 파일 로거(로그 수준.경고   로그 수준.오류));          // 콘솔에 모든 로그 수준이 있으므로 콘솔 로거에서 처리         노상강.메시지("입력 기능 ProcessOrder().", 로그 수준.디버그);         노상강.메시지("주문기록 회수", 로그 수준.정보);          // FileLogger가 Warning & Error를 구현하므로 ConsoleLogger 및 FileLogger에서 처리됨         노상강.메시지("Branch DataBase에 고객 주소 세부 정보가 누락됨.", 로그 수준.경고);         노상강.메시지("Organization DataBase에 고객 주소 세부 정보가 누락됨.", 로그 수준.오류);          // 기능 오류를 구현할 때 ConsoleLogger 및 EmailLogger에서 처리         노상강.메시지("고객 C1을 위해 D1일자 주문 ORD1을 처리할 수 없음.", 로그 수준.FunctionalError);          // ConsoleLogger 및 EmailLogger에서 처리         노상강.메시지("발송주문.", 로그 수준.FunctionalMessage);     } }   /* 출력 콘솔에 쓰기:ProcessOrder() 함수를 입력하는 중. 콘솔에 쓰기:주문 기록 검색됨 콘솔에 쓰기:Branch DataBase에 고객 주소 세부 정보가 누락됨 로그 파일에 쓰기: Branch DataBase에 고객 주소 세부 정보가 누락됨 콘솔에 쓰기:Organization DataBase에 고객 주소 세부 정보가 누락됨 로그 파일에 쓰기: Organization DataBase에 고객 주소 세부 정보가 누락됨 콘솔에 쓰기:고객 C1에 대해 D1일자 주문 ORD1을 처리할 수 없음. 전자 메일로 보내기:고객 C1에 대해 D1일자 주문 ORD1을 처리할 수 없음. 콘솔에 쓰기:주문 발송됨. 전자 메일로 보내기:주문 발송됨. */ 

크리스탈 예제

열거하다 로그 수준   없음   정보   디버그   경고   오류   FunctionalMessage   FunctionalError   전부 종지부를 찍다  추상적 계급 로거   재산 log_message   재산 다음에 : 로거       반항하다 초기화하다(*레벨)     @log_message = []  로그 수준      레벨.각각 하다  수평을 이루다        @log_message << 수평을 이루다     종지부를 찍다   종지부를 찍다    반항하다 메세지(음스그 : , 엄격함 : 로그 수준)     만일 @log_message.포함하시겠습니까?(로그 수준::전부)    @log_message.포함하시겠습니까?(엄격함)       write_message(음스그)     종지부를 찍다     @다음.해보다(&메세지(음스그, 엄격함))   종지부를 찍다    추상적 반항하다 write_message(음스그 : ) 종지부를 찍다  계급 콘솔로거 < 로거   반항하다 write_message(음스그 : )     놓다 "콘솔에 쓰기:#{음스그}"   종지부를 찍다 종지부를 찍다  계급 EmailLogger < 로거   반항하다 write_message(음스그 : )     놓다 "메일을 통해 전송:#{음스그}"   종지부를 찍다 종지부를 찍다  계급 파일 로거 < 로거   반항하다 write_message(음스그 : )     놓다 "로그 파일에 쓰기:#{음스그}"   종지부를 찍다 종지부를 찍다  # 프로그램 # 책임의 사슬을 구축 노상강 = 콘솔로거.새로운(로그 수준::전부) 로거1 = 노상강.다음에 = EmailLogger.새로운(로그 수준::FunctionalMessage, 로그 수준::FunctionalError) 로거2 = 로거1.다음에 = 파일 로거.새로운(로그 수준::경고, 로그 수준::오류)  # 콘솔에 모든 로그 레벨이 있으므로 콘솔 로거에서 처리 노상강.메세지("입력 기능 ProcessOrder().", 로그 수준::디버그) 노상강.메세지("주문기록 회수", 로그 수준::정보)  # FileLogger가 Warning & Error를 구현하므로 ConsoleLogger와 FileLogger에서 처리 노상강.메세지("Branch DataBase에 고객 주소 세부 정보가 누락됨.", 로그 수준::경고) 노상강.메세지("Organization DataBase에 고객 주소 세부 정보가 누락됨.", 로그 수준::오류)  # 기능 오류를 구현하면서 ConsoleLogger 및 EmailLogger에서 처리 노상강.메세지("고객 C1을 위해 D1일자 주문 ORD1을 처리할 수 없음.", 로그 수준::FunctionalError)  # ConsoleLogger 및 EmailLogger에서 처리 노상강.메세지("발송주문.", 로그 수준::FunctionalMessage) 

출력

콘솔에 쓰기:ProcessOrder() 함수를 입력하는 중.콘솔에 쓰기:주문 기록 검색됨콘솔에 쓰기:Branch DataBase에 고객 주소 세부 정보가 누락됨로그 파일에 쓰기: Branch DataBase에 고객 주소 세부 정보가 누락됨콘솔에 쓰기:Organization DataBase에 고객 주소 세부 정보가 누락됨로그 파일에 쓰기: Organization DataBase에 고객 주소 세부 정보가 누락됨콘솔에 쓰기:고객 C1에 대해 D1일자 주문 ORD1을 처리할 수 없음.전자 메일로 보내기:고객 C1에 대해 D1일자 주문 ORD1을 처리할 수 없음.콘솔에 쓰기:주문 발송됨.전자 메일로 보내기:주문 발송됨. 

Python 3 예제

""" 책임 패턴의 체인 예. """ 로부터 a b c 수입하다 ABC메타, 추상적인 방법 로부터 열거하다 수입하다 열거, 자동차로   계급 로그 수준(열거):     """ 로그 수준 열거."""     없음 = 자동차로()     정보 = 자동차로()     디버그 = 자동차로()     경고 = 자동차로()     오류 = 자동차로()     기능_메시지 = 자동차로()     기능_오류 = 자동차로()     모두 = 자동차로()   계급 로거:     """책임 패턴 체인의 추론 핸들러."""     __metaclass___ = ABC메타      다음에 = 없음      반항하다 __init___(자아의, 레벨) -> 없음:         """새 로거 초기화.  인수: 수준(list[str]):로그 수준 목록. """         자아의.log_message = []          을 위해 수평을 이루다  레벨:             자아의.log_message.덧셈을(수평을 이루다)      반항하다 set_next(자아의, next_snow: 로거):         """"다음 책임 로거를 체인에서 설정하십시오.  인수: next_logger(로거):다음 책임 로거. Returns: Logger: 다음 담당 로거. """         자아의.다음에 = next_snow         돌아오다 자아의.다음에      반항하다 메세지(자아의, 음스그: 발을 동동 구르다, 엄격함: 로그 수준) -> 없음:         """메시지 작성기 취급자.  인수: msg(str):메시지 문자열. 심각도(로그 수준):로그 수준 열거형 메시지 심각도. """         만일 로그 수준.모두  자아의.log_message 또는 엄격함  자아의.log_message:             자아의.write_message(음스그)          만일 자아의.다음에 이다 아닌 없음:             자아의.다음에.메세지(음스그, 엄격함)      @abstractmethod     반항하다 write_message(자아의, 음스그: 발을 동동 구르다) -> 없음:         """"메세지를 쓰는 추론 방법.  인수: msg(str):메시지 문자열. 상승:구현되지 않음Error """         높이다 구현되지 않음Error("이 방법을 실행해야 해.")   계급 콘솔로거(로거):     반항하다 write_message(자아의, 음스그: 발을 동동 구르다) -> 없음:         """부모의 추상적인 방법 위로 쓰기 오버라이드.  인수: msg(str):메시지 문자열. """         인쇄하다("위로를 위한 쓰기: ", 음스그)   계급 EmailLogger(로거):     """부모의 추상적인 방법을 오버라이드하여 이메일을 보낸다.  인수: msg(str):메시지 문자열. """     반항하다 write_message(자아의, 음스그: 발을 동동 구르다) -> 없음:         인쇄하다(f"메일을 통해 전송:{음스그}")   계급 파일 로거(로거):     """파일을 쓰는 부모의 추상적인 방법을 덮어쓴다.  인수: msg(str):메시지 문자열. """     반항하다 write_message(자아의, 음스그: 발을 동동 구르다) -> 없음:         인쇄하다(f"로그 파일에 쓰기:{음스그}")   반항하다 본래의():     """책임의 사슬을 쌓는다."""     노상강 = 콘솔로거([로그 수준.모두])     e-메일_메일 = 노상강.set_next(         EmailLogger([로그 수준.기능_메시지, 로그 수준.기능_오류])     )     # 나중에 파일 로거 인스턴스를 사용할 필요가 없으므로     # 우리는 그것에 대해 어떤 가치도 설정하지 않을 것이다.     e-메일_메일.set_next(         파일 로거([로그 수준.경고, 로그 수준.오류])     )      # 메시지 이후 콘솔로거가 이 코드 부분을 처리함     # 전체 로그 수준     노상강.메세지("입력 기능 ProcessOrder().", 로그 수준.디버그)     노상강.메세지("주문기록 회수", 로그 수준.정보)      # ConsoleLogger 및 FileLogger는 파일 로거 이후 이 부분을 처리함     # 경고 및 오류 구현     노상강.메세지(         "Branch DataBase에 고객 주소 세부 정보가 누락됨.",         로그 수준.경고     )     노상강.메세지(         "Organization DataBase에 고객 주소 세부 정보가 누락됨.",         로그 수준.오류     )      # ConsoleLogger 및 EmailLogger가 구현 시 이 부분을 처리함     # 기능적 오류     노상강.메세지(         "고객 C1에 대한 주문 ORD1 D1 날짜 처리 불가.",         로그 수준.기능_오류     )     노상강.메세지("발송주문.", 로그 수준.기능_메시지)   만일 __name__ == "__main__":     본래의() 

PHP 예제

<?php  추상적 계급 로거 {      /** * 심각도에 대한 비트 마스크 플래그 */     공중의 경시하다 없음 = 0;     공중의 경시하다 정보 = 0b000001;     공중의 경시하다 디버그 = 0b000010;     공중의 경시하다 경고 = 0b000100;     공중의 경시하다 오류 = 0b001000;     공중의 경시하다 기능_메시지 = 0b010000;     공중의 경시하다 기능_오류 = 0b10,000;     공중의 경시하다 모두 = 0b11111;      /*** @var int 이 클래스의 비트 마스크 플래그.*/     보호의 인트로 $logMask;      /**** @var \Logger null */ 메시지를 처리할 옵션 다음 로거     보호의 ?로거 다음불 = 무효의;      /** * 로거 생성자. * * @param int $mask * 이 클래스의 비트 마스크 플래그. */     공중의 기능을 발휘하다 ____(인트로 달러마스크)     {         $ this->로그마스크 = 달러마스크;     }      /** * 체인에서 다음 담당 로거를 설정하십시오. * * @param \Logger $nextLogger * 다음 책임 로거. * * @return \Logger *로거: 다음 담당 로거. */     공중의 기능을 발휘하다 setNext(로거 $nextLogger): 로거     {         $ this->다음에 = $nextLogger;          돌아오다 $nextLogger;     }      /** * 메시지 작성기 처리기 * * @param 문자열 $msg * 메시지 문자열. * @param int $propert * 이 클래스의 비트 마스크 플래그로서 메시지의 심각도 * * @return $ this */     공중의 기능을 발휘하다 메세지(끈을 매다 $msg, 인트로 달러화): 로거     {         만일 (달러화 & $ this->로그마스크) {             $ this->writeMessage($msg);         }         만일 ($ this->다음에 !== 무효의) {             $ this->다음에->메세지($msg, 달러화);         }          돌아오다 $ this;     }      /** * 메시지를 작성하는 추상적인 방법 * * @param 문자열 $msg * 메시지 문자열. */     추상적 보호의 기능을 발휘하다 writeMessage(끈을 매다 $msg): 공허하게 하다;  }  계급 콘솔로거 연장하다 로거 {      보호의 기능을 발휘하다 writeMessage(끈을 매다 $msg): 공허하게 하다     {         메아리치다 "콘솔에 쓰기:$msg\n";     }  }  계급 EmailLogger 연장하다 로거 {      보호의 기능을 발휘하다 writeMessage(끈을 매다 $msg): 공허하게 하다     {         메아리치다 "메일을 통해 전송:$msg\n";     }  }  계급 파일 로거 연장하다 로거 {      보호의 기능을 발휘하다 writeMessage(끈을 매다 $msg): 공허하게 하다     {         메아리치다 "로그 파일에 쓰기:$msg\n";     }  }  달러화 = 새로운 콘솔로거(로거::모두); 달러화     ->setNext(새로운 EmailLogger(로거::기능_메시지   로거::기능_오류))     ->setNext(새로운 파일 로거(로거::경고   로거::오류));  달러화     // 콘솔에 모든 로그 수준이 있으므로 콘솔 로거에서 처리     ->메세지("입력 기능 ProcessOrder().", 로거::디버그)     ->메세지("주문기록 회수", 로거::정보)     // FileLogger가 Warning & Error를 구현하므로 ConsoleLogger 및 FileLogger에서 처리됨     ->메세지("Branch DataBase에 고객 주소 세부 정보가 누락됨.", 로거::경고)     ->메세지("Organization DataBase에 고객 주소 세부 정보가 누락됨.", 로거::오류)     // 기능 오류를 구현할 때 ConsoleLogger 및 EmailLogger에서 처리     ->메세지("고객 C1을 위해 D1일자 주문 ORD1을 처리할 수 없음.", 로거::기능_오류)     // ConsoleLogger 및 EmailLogger에서 처리     ->메세지("발송주문.", 로거::기능_메시지);  /* 출력 콘솔에 쓰기:ProcessOrder() 함수를 입력하는 중. 콘솔에 쓰기:주문 기록 검색됨 콘솔에 쓰기:Branch DataBase에 고객 주소 세부 정보가 누락됨 로그 파일에 쓰기:Branch DataBase에 고객 주소 세부 정보가 누락됨 콘솔에 쓰기:Organization DataBase에 고객 주소 세부 정보가 누락됨 로그 파일에 쓰기:Organization DataBase에 고객 주소 세부 정보가 누락됨 콘솔에 쓰기:고객 C1에 대해 D1일자 주문 ORD1을 처리할 수 없음. 전자 메일로 보내기:고객 C1에 대해 D1일자 주문 ORD1을 처리할 수 없음. 콘솔에 쓰기:주문 발송됨. 전자 메일로 보내기:주문 발송됨. */ 

구현

코코아 및 코코아 터치

각각 OS XiOS 애플리케이션에 사용되는 코코아코코아 터치 프레임워크는 이벤트 처리에 책임 체인 패턴을 적극적으로 사용한다.체인에 참여하는 개체를 응답기 개체라고 하며, 이 개체로부터 상속된다.NSResponder(OS X)/UIResponder(iOS) 클래스.모든 뷰 객체(NSView/UIView(), 컨트롤러 개체 보기(NSViewController/UIViewController)), 창 객체 (NSWindow/UIWindow() 및 애플리케이션 개체(NSApplication/UIApplication)는 응답자 객체다.

일반적으로, 뷰가 처리할 수 없는 이벤트를 수신하면, 뷰 컨트롤러나 윈도우 객체에 도달할 때까지 수퍼뷰로 전송한다.윈도우가 이벤트를 처리할 수 없는 경우, 이벤트는 체인에서 마지막 객체인 애플리케이션 객체에 디스패치된다.예를 들면 다음과 같다.

  • OS X에서는 슬라이더 컨트롤과 같은 드래그 이벤트를 처리하는 뷰가 없는 한 마우스로 텍스트화된 창을 이동할 수 있다(제목 표시줄만이 아님).이러한 보기(또는 수퍼뷰)가 없는 경우 끌기 이벤트를 처리하는 창으로 끌기 이벤트가 체인으로 전송된다.
  • iOS에서는 일반적으로 보기 자체를 하위 분류하는 대신 보기 계층을 관리하는 보기 컨트롤러에서 보기 이벤트를 처리하는 것이 일반적이다.뷰 콘트롤러는 모든 관리되는 하위 뷰 이후에 응답기 체인에 있으므로, 뷰 이벤트를 가로채서 처리할 수 있다.

참고 항목

참조

  1. ^ "Archived copy". Archived from the original on 2018-02-27. Retrieved 2013-11-08.{{cite web}}: CS1 maint: 타이틀로 보관된 사본(링크)
  2. ^ Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley. pp. 223ff. ISBN 0-201-63361-2.{{cite book}}: CS1 maint : 복수이름 : 작성자 목록(링크)
  3. ^ "The Chain of Responsibility design pattern - Problem, Solution, and Applicability". w3sDesign.com. Retrieved 2017-08-12.
  4. ^ "The Chain of Responsibility design pattern - Structure and Collaboration". w3sDesign.com. Retrieved 2017-08-12.