관찰자 패턴에 비해 델리게이트 패턴의 장점은 무엇입니까?


9

에서 위임 패턴 , 하나의 개체가 직접 다른 개체의 이벤트를 수신 할 수 있습니다. 에서 관찰자 패턴 , 객체의 수는 특정 개체의 이벤트를 수신 할 수 있습니다. 다른 객체에 이벤트를 알리는 클래스를 설계 할 때 왜 옵저버 패턴보다 델리게이트 패턴을 사용하겠습니까? 관찰자 패턴이 더 유연하다고 생각합니다. 지금은 하나의 관찰자 만있을 수 있지만 향후 디자인에는 여러 개의 관찰자가 필요할 수 있습니다.


4
"위임 패턴"이란 무엇입니까? .net의 대리인과 같은 것에 대해 이야기하고 있다면 원하는만큼 가입자를 가질 수 있습니다.
코드 InChaos

답변:


7

델리게이트 패턴 자체는 없습니다. 위임 패턴 을 의미한다고 가정하겠습니다 .

내가 이해하는 것처럼, 그것들은 서로 완전히 반대이며 다른 목적으로 사용됩니다.

일반적으로 Observer Pattern을 사용 하면 임의의 수의 옵저버 객체가 두 번째 객체의 이벤트를 수신하고 이벤트에 작용합니다. 두 번째 객체는 리스너에 대한 지식이 없습니다. 그것은 단지 그들에게 전화합니다.

델리게이트 오브젝트는 델리게이트에서 직접 메소드를 호출하는 두 번째 오브젝트로 전달됩니다. 그리고 당신이 찾고있는 장점이 있습니다. 단일 메시지를 여러 리스너에게 보내지 않고 단일 객체를 주어진 시간에 완벽하게 제어 할 수 있습니다. 제어 반전을 참조하십시오 .


6

일을 잘못보고 있습니다. 관찰자는 특정 이벤트가 발생하는 것을 확인합니다. 영향을 주거나 소유하지 않습니다. 델리 게이터가 이벤트에 대한 인터페이스를 소유하더라도 위임 특정 이벤트를 처리 하고 핸들러의 소유권을 갖습니다.


1
델리게이트는 실제로 이벤트 관찰자에 지나지 않습니다. 대리인은 아무것도 "처리"할 필요가 없습니다. 안전하게 아무 것도 할 수 없으며 이벤트를 트리거 한 인스턴스에 영향을 미치지 않습니다.
Marjan Venema

5
@MarjanVenema은 - 객체 A가되지 않은 경우 위임 객체 B에 이벤트에 대한 책임을, 당신은 위임 패턴을 사용하지 않는 : 당신이 하나의 관찰자와 관찰자 패턴을 사용하고 있습니다.
Telastyn

네, 제가 생각한 것입니다. "OnWhatever"이벤트 가입자가 사용할 이벤트 서명 유형으로 위임되었음을 이해했습니다. C #의 델리게이트는 델파이와 같이 단일 가입자가 아닌 것으로 보입니다.
Marjan Venema

@Marjan Venema "대리인은 이벤트를 관찰하는 사람에 지나지 않습니다." 그것은 당신이 말하는 언어에 달려 있습니다. Objective C에서 일부 대의원은 데이터 (예 : 데이터 대의원)를 제공 할 책임이 있으며, 데이터 대의원이 누락 된 개체에는 제시 할 데이터가 없습니다. 그러한 경우, 단지 무언가를 관찰하는 행위와는 별개로 위임이 진행되고 있습니다.
occulus December

1
@occulus : 설명해 주셔서 감사합니다. 언어가 용어에 대해 동의 할 수없는 것이 유감입니다 ... 사람들이 같은 단어에 대해 다른 것을 이해하면 언어에 관계없이 프로그래밍에 대해 이야기하는 것은 조금 어려워집니다.
Marjan Venema

4

그것은 몇 가지 상충 관계의 문제입니다.

절충 :

  • 유연성 (n> 1 대의원 / 관찰자 보유 측면에서)
  • 메시지를 보내는 비용
  • 복원력 (대리인 / 관찰자의 사용 불가능 유지 능력)
  • 사용의 용이성

델리게이트 패턴 :

  • 매우 유연하지 않음-둘 이상의 대리자를 추가 할 수 없습니다 (일부 형태의 "다중 델리게이트", 즉 관찰자 패턴 포함)
  • 메시지 전송 비용이 저렴합니다. O (1)-다른 함수 나 메소드 호출과 동일한 비용 (조회, 메시지 대기열 또는 기타 인프라 필요 없음)
  • 일반적으로 탄력적이지 않음-델리게이트가 참석하여 작업의 일부를 수행해야합니다. 즉, 델리게이트가 알려지지 않은 경우 발신자가 실패하는 경향이 있습니다.
  • 이해하기 쉽고 구현하기 쉽다

관찰자 패턴 :

  • 매우 유연함-설계 상 n> 1 옵저버 추가
  • 메시지를 보내는 데는 옵저버 수 O (n)가 내포 한 비용이 있습니다. 즉, n 개의 옵저버는 n 번의 시간과 메시지를받습니다 (적어도 순진한 구현에서는)
  • 일반적으로 탄력적-관찰자는 일반적으로 발신자의 일부 작업을 수행하지 않아도됩니다. 관찰자가없는 경우에도 발신자가 영향을받지 않습니다.
  • 특히 관찰자가 메시지에 반응 할 것으로 예상됩니다 (순서가 중요합니까? 어떤 관찰자가 어떤 방식으로 응답합니까?)

1

내가 아는 것처럼 델리게이트 패턴은 다른 언어 (예 : Delphi)의 이벤트 핸들러 메커니즘으로 알려져 있습니다. 따라서 이는 한 번에 하나의 리스너 만 주요 제한이있는 옵저버 패턴의 구현입니다.

이벤트 핸들러 또는 델리게이트의 단점은 명백합니다. 단 하나의 관찰자입니다.

장점은 분명하지 않습니다. 성능. 관찰자 패턴을 사용하면 많은 관찰자를 추가 할 수 있습니다. 관찰자에게 알림이 필요한 이벤트가 발생하면 관찰자를 열거하고 각각에 알림을 보내야합니다. 이는 특히 알림이 필요한 이벤트의 수가 많은 경우 관찰 된 인스턴스를 빠르게 정리할 수 있습니다.


응? C # 대리자는 변수 형식 (예 : int (*my_int_f)(int)C) 과 같은 메서드의 서명일뿐입니다 . 나는 항상 그들이 struct / enum처럼 작동하게함으로써 이해하기 쉽게 만들 것이라고 생각했습니다. 이벤트는 단일 델리게이트 서명을 사용하여 유연한 리스너 배열을위한 후크입니다. 당신은 할 수 있지만, 언어가 쉽게 그것을하고있다 (나는 매우 다르다 영업 의미 위임 패턴, 가정 이유입니다) 이벤트없이 그렇게.
pdr December

흠. 아직 C #에 정통하지는 않습니다. 델파이와 같이 "OnWhatever"이벤트에서 사용되는 델리게이트가 이벤트 서명 유형과 동등한 것으로 이해했습니다. 그래서 C # 이벤트는 여러 리스너가 구독 할 수 있습니까?
Marjan Venema

일반 Action <T>는 대리자입니다. 이벤트와 관련이 없으며 전달되는 변수입니다. 그리고 여러 청취자가 하나의 이벤트를들을 수 있습니다.
pdr December

알았어 고마워, 내가 똑바로 유지할 수 있기를 바랍니다 ... :-) C # 참조를 꺼내고 이벤트 메커니즘에 더 집중했습니다.
Marjan Venema

1

이것은 오래된 게시물이지만 어쨌든 다른 대답은 어느 패턴을 사용할 때 일어나는 일을 다루지 않기 때문에 연습보다 이론에 관한 것 같습니다.

위임 및 관찰자 작동 방식

위임을 통해 위임자는 잠재적 인 이벤트의 소스가 생성되는 순간 특정 이벤트에 응답 할 사람을 정확하게 선택합니다. 이 청취자를 단일 관찰자 로 생각할 수 있습니다. 관찰자 패턴의 경우 관찰자는 자신이 느낄 때마다 관찰중인 사람을 선택합니다. 따라서 관찰자 대 위임과 관련하여 종속성이 반전됩니다. 관찰자 패턴으로 신문과 구독자를 관찰자로 생각하십시오. 관찰자는 관계가 생성되는시기를 제어합니다. 대표단과 함께 직원과 고용주를 생각하십시오. 고용주는 관계가 생성되는 시점과 특정 이벤트를 담당하는 사람을 정확하게 관리합니다. 직원들은 일반적으로 어떤 작업을하고 있는지 선택할 수 없습니다.

일부 대표단은 한 명의 관찰자를 가질 수 있지만 두 가지의 실제 차이점은 이벤트 처리가 할당되는 방식이라고 생각합니다. 이벤트에 대한 델리게이트 레지스터는 표시되지 않습니다. 이벤트가 발생하고 위임자가 공개 메소드를 호출 할 때까지 이벤트 처리조차 알 수 없습니다.

위임장

이 패턴은 매우 단단하며 대부분의 레지 드 디자인에서는 더 단순하고 일반적으로 더 견고합니다. 잠재적 인 이벤트의 소스를 초기화 할 때 이벤트 핸들러를 미리 선언하도록합니다. 직접 통행 할 사람이 필요한 경우 길을 열기 전에 교통 감독을 지정하십시오. 관찰자의 경우, 교통 경찰이 자신이 느끼는대로 언제든지 교통을 지시 할시기를 선택하게 할 것입니다.

위임 단점

이 디자인의 단점은 융통성이 없다는 것입니다. 신문을 구독하기위한 몇 가지 코드를 구현하는 경우 신문 / 대리인은 뉴스 기사를 작성할 때 뉴스 기사를 읽을 수있는 사람을 정확히 식별해야합니다. 관찰자 패턴을 사용하면 언제든지 나중에 등록 할 수 있으며 신문은 새로운 사람이 가입했다는 사실 만 알면됩니다.

위임을 언제 선택해야합니까?

특정 관찰자가 하나 필요하고 관찰중인 사람을 변경할 이유가없는 경우 위임 패턴의 엄격한 설계가 도움이됩니다.

예를 들어 특정 오류에 대한 팝업 작성을 처리하려면 클래스 / 객체가 필요합니다. 런타임시 특정 오류를 처리하는 사람을 전환해야하는 이유는 많지 않으므로 "메모리 부족"오류를 단일 엔티티로 위임하는 것이 합리적입니다. 잠재적 인 핸들러 배열을 만든 다음 해당 핸들러가 "메모리 부족"오류에 등록되도록하는 것은 그리 의미가 없습니다. 이것이이 상황에서 옵저버 패턴을 사용하는 예입니다. 런타임에 변수 이벤트에 대해 호출되는 메소드 또는 "대리인"이 변경되는 것을 변경하려고 할 수 있지만 런타임에 특정 이벤트에 대한 이벤트 핸들러를 교체하는 것은 정상적이지 않습니다.

옵저버 패턴에서와 같이 델리게이트를 교체하는 것은 불가능하지 않습니다. 현실에서는 아마도 새로운 경찰이 트래픽을 처리하도록 트래픽 경찰을 교환하고 싶을 것입니다. 더 나은 디자인은 원래 대의원을 경찰서로 만들지 만 한 명의 경찰관이 아니라고 나는 주장합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.