2012-06-11 2 views
16

나는이 디자인 문제에 대한 청결한 답변을 찾지 못했습니다. ".NET Framework design guidelines"도 아니고 "C# programing guidelines"도 도움을받을 수 없습니다.대리자 (람다 식) 대 인터페이스 및 추상 클래스

1)

// This what I provide 
public abstract class AbstractDoSomething{ 
    public abstract SomeThing DoSomething(); 
} 

사용자는이 추상 클래스를 구현 필요 그들은 : 사용자가 정의하고이 같은 내 프레임 워크에 자신의 알고리즘을 통합 할 수 있도록 나는 기본적으로 API로 패턴을 노출해야 (나는 그것을 내 프레임 워크 내에서 전화를 사용할 수있는)

2)

,536 DoSomething 방법을 구현해야 사용자는이 방법 DoSomething 클래스를 사용할 수 있습니다이 경우

public sealed class DoSomething{ 
    public String Id; 
    Func<SomeThing> DoSomething; 
} 

:

나는이 또한 사용 대의원 acheived 수 있다는 것을 발견

DoSomething do = new DoSomething() 
{ 
    Id="ThisIsMyID", 
    DoSomething = (() => new Something()) 
} 

질문

을 어느 이 두 가지 옵션 중 은 가장 쉽고 유용하며 가장 중요한 것은 API로 노출되는입니다. 1 경우

편집

: 등록이 방법으로 이루어진다는 (MyDoSomething 가정은 AbstractDoSomething 연장 :

2 경우
MyFramework.AddDoSomething("DoSomethingIdentifier", new MyDoSomething()); 

: 등록은 다음과 같이 이루어진다 :

MyFramework.AddDoSomething(new DoSomething()); 
+0

사용자가 프레임 워크에 AbstractDoSomethings을 어떻게 등록합니까? – dtb

+0

@dtb 내 편집 내용을 참조하십시오 (코드도 약간 수정 됨) – GETah

답변

15

API로 공개하기 쉽고 사용하기 쉽고 가장 중요하게 이해할 수있는 두 가지 옵션은 무엇입니까?

첫 번째 버전은 OOP 측면에서 더 "전통적"이며 더 많은 개발자가 이해할 수 있습니다. 또한 사용자가 객체의 수명을 관리 할 수있는 장점이 있습니다 (예 : 클래스가 IDisposable을 구현하도록하고 종료시 인스턴스를 삭제할 수 있음). 또한 향후 버전에서 쉽게 확장 할 수 있습니다. 기본 클래스에 가상 멤버를 추가해도 API가 중단되지 않으므로 이전 버전과의 호환성은 손상되지 않습니다. 마지막으로 MEF와 같은 것을 자동으로 작성하려면 사용자의 관점에서 "등록"프로세스를 단순화/제거 할 수 있습니다 (서브 클래스를 생성하여 폴더를 만들고 자동으로 검색/사용하도록 설정하십시오.

두 번째는 더 기능적인 접근 방식이며 여러면에서 더 간단합니다. 이를 통해 사용자는 기존 코드의 변경 사항을 훨씬 줄여 API를 구현할 수 있습니다. 새 유형을 만드는 대신 람다에 필요한 호출을 클로저로 래핑하면됩니다.

당신이 대리자를 사용하는 접근 방식을 취할려고하는 경우에, 심지어 사용자가 클래스를 생성하지 것이다 있음을 의미하며,

- 단지 같은 방법을 사용

MyFramework.AddOperation("ThisIsMyID",() => DoFoo()); 

이 그것을 만드는을 제 의견으로는 시스템에 직접 작업을 추가한다는 것이 조금 더 명확합니다. 또한 공개 API (DoSomething)에서 다른 유형의 필요성을 완전히 제거하므로 API가 다시 간소화됩니다.

+0

+1. 귀하의 답변에 감사드립니다. 'Func'을 내 프레임 워크에 직접 등록하는 문제는 앞으로 해당 기능을 확장 할 수 없다는 것입니다 (DoSomething에 동작을 추가 할 수 없음). – GETah

+0

@GETah 내 게시물에서 언급했듯이, 행동을 추가하면 수업이 더 좋습니다. (가상 멤버 추가에 대한 문장을 참조하십시오.) 즉, 대리인 대신 클래스를 사용하는 것이 IMO입니다. –

+0

아하이. 귀하의 의견에 감사드립니다. – GETah

6

나는 경우 추상 클래스/인터페이스와 함께 갈 것입니다 :

  • 해봐요은
  • 해봐요 일반적으로 정말 큰 얻을 것이다 필요는
(이렇게 해봐요의 구현은 여러/개인 보호 방법에 splited 할 수 있습니다)

전 대표와 함께 갈 것 같은 경우

  • DoSomethi NG는 이벤트 (OnDoingSomething)
  • 해봐요은 선택 사항 (그래서 당신은 어떤 조합의 위임에 기본값)
  • 이러한 유형의 질문의 대부분 그렇듯이
1

, 나는 그것이 "말할 것으로 간주 될 수있다 의존한다 ". :)

하지만 추상 클래스와 람다를 사용하는 이유는 실제로 작동에 있다고 생각합니다. 일반적으로 람다는 콜백 유형의 기능으로 사용됩니다. 뭔가 다른 일이 발생할 때 커스텀이 발생하기를 원합니다. 나는 나의 클라이언트 측 코드에서이 많이을 수행 를 - 지금 따라

당신은 람다와 동일한 작업을 수행 할 수있는 데이터를 처리하기 위해 내 콜백을 호출 - - 을 일부 데이터를 다시 얻을 - 서비스 호출 만들 그들은 구체적이고 매우 구체적인 상황을 목표로합니다.

추상 클래스 (또는 인터페이스)를 사용하면 실제로 클래스의 동작이 주변 환경에 의해 유도되는 위치가됩니다. 무슨 일이 일어나고 있고, 내가 어떤 고객을 다루고 있는가? 이러한 큰 질문은 일련의 행동을 정의한 다음 개발자 (또는 API 사용자)가 자신의 요구 사항에 따라 고유 한 동작 집합을 만들 수 있음을 제안 할 수 있습니다. 허락하신다면, 당신은 람다 (lambdas)로도 똑같이 할 수 있지만, 개발하는 것이 더 복잡 할 것이고, 또한 사용자와 명확하게 의사 소통하기가 더 복잡 할 것이라고 생각합니다.

이렇게 내 엄숙한 규칙은 다음과 같습니다. - 특정 콜백 또는 부작용 사용자 정의 동작에 람다를 사용합니다. - 추상 클래스 또는 인터페이스를 사용하여 객체 비헤이비어 사용자 정의 (또는 적어도 객체의 기본 비헤이비어 대부분)에 대한 메커니즘을 제공합니다.

죄송합니다. 명확한 정의는 아니지만 도움이 되었기를 바랍니다. 행운을 빕니다! 고려해야 할

1

몇 가지 :

얼마나 많은 다른 기능/대표 쟁이 오버 할 필요가? 함수가있을 수있는 경우, inheretance는 오버라이드의 "세트"를 이해하기 쉬운 방식으로 그룹화합니다. 하나의 "등록"기능을 가지고 있지만 많은 하위 부분이 구현 자에게 위임 될 수있는 경우, 이는 "템플리트"패턴의 고전적인 경우이며, 이는 상속 될 수있는 가장 합리적인 것입니다.

같은 기능을 몇 가지 구현해야합니까? 하나뿐이라면 불충분 함은 좋지만 구현이 많으면 대리인이 오버 헤드를 줄일 수 있습니다.

구현이 여러 개인 경우 프로그램간에 전환해야합니까? 또는 단일 구현 만 사용합니다. 전환이 필요하면 대리인이 쉬울 수도 있지만 특히 # 1에 대한 답변에 따라주의해야합니다. 전략 패턴을 참조하십시오.

재정의가 보호 된 구성원에 대한 액세스가 필요한 경우 부적절합니다. 그것이 대중에게만 의지 할 수 있다면, 대의원.

기타 선택 사항으로는 이벤트 및 확장 방법이 있습니다.

2

개인적으로는 내 손안에는 항상 대리모 모델을 사용합니다. 나는 고차원 기능의 단순함과 우아함을 좋아한다. 그러나 모델을 구현하는 동안 메모리 누수에주의하십시오. 구독 이벤트는 .Net에서 메모리 누수가 발생하는 가장 일반적인 이유 중 하나입니다. 즉, 일부 이벤트가 노출 된 오브젝트가있는 경우, 이벤트가 강력한 참조를 작성하기 때.에 모든 이벤트가 등록 취소 될 때까지 원래 오브젝트가 h 제되지 않습니다.

+1

답변 해 주셔서 감사합니다. API를 만들 때 불행히도 당신이 좋아하는 것이지만 다른 사람들이 좋아하는 것 : p – GETah