2013-05-21 3 views
2

필자는 generic 클래스를 가지고 있는데, MyClass<T>이라고 부르 자. 팩토리 메소드가 있어야 클라이언트 코드에서 생성자 세부 사항을 추상화 할 수있다.제네릭 또는 비 제네릭 클래스의 정적 팩토리 메서드입니까?

두 가지 옵션 중 올바른 것은 무엇입니까? 전용에

MyClass<SomeType> instance = MyClass<SomeType>.CreateNew(); 
  • 정적 일반 공장에있어서 원래 일반MyClass<T>

    1. 정적 아닌 일반 공장 메소드 (예를 인스턴스화 코드 포함) 비 일반 정적 MyClass 구현 tation : 귀하의 질문에 대한 적절한 답변이 1 #이처럼 첫눈에

      MyClass<SomeType> instance = MyClass.CreateNew<SomeType>(); 
      
  • +0

    이 질문은 [당신의 가장 논란이되는 프로그래밍 견해는 무엇입니까?] (http://stackoverflow.com/questions/406760/whats-your-most-controversial-programming-opinion)에 대한 좋은 후보라고 생각하지만 C# 언어 –

    답변

    1

    이 보인다. 이는 귀하의 수업이 MyClass<T>이기 때문에 공장도 T- 특정이어야하기 때문입니다. 그러나이 간단한 대답보다 더 많은 것이 있습니다.

    계속하기 전에 세 번째 가능성을 추가 할 것입니다. 비 정적 팩토리 클래스. 팩토리를 사용하는 객체는 팩토리 객체를받는 공용 속성을 갖습니다. 다른 인스턴스가 지정되어 있지 않으면 속성의 Getter가 기본 팩토리를 인스턴스화합니다. 이렇게하면 나중에 종속성 주입을 허용하고 자신의 위조 된 공장에 의존하는 단위 테스트를 작성하는 데 도움이됩니다. 솔루션 (잠시 제네릭을 무시)과 같이 보일 것입니다 :

    public class ISomeFactory { ... } 
    
    public class DefaultSomeFactory: ISomeFactory { ... } 
    
    public class ClientClass 
    { 
        public ISomeFactory FactoryOfSome // Right place for dependency injection 
        { 
         get 
         { 
          if (_fact == null) 
           _fact = new DefaultFactory(); 
          return _fact; 
         } 
         set { _fact = value; } 
        } 
        private ISomeFactory _fact; 
    } 
    

    을 지금 말했듯이, 클래스 제네릭 매개 변수 MyClass<T>로 이동 한 후 공장뿐만 아니라 일반적인 매개 변수와 함께 가야한다 : Factory<T>가. 이 솔루션은 일반 팩토리의 일반 메소드보다 낫습니다. 인스턴스를 생성하는 것이 T 특정 일 수 있기 때문입니다. 당신은 기존의 팩토리 클래스의 행동을 무시하고 문자열에 대한 전문화되어 인스턴스를 생성하는 다른 방법을 가질 수있다, 이런 식으로

    public class SpecialSomeFactory: DefaultSomeFactory<string> { ... } 
    

    : 일반 공장 솔루션은 당신이 할 수 있습니다. 문자열을 다루는 것이 int 나 double과 같은 원시 타입을 다루는 것보다 훨씬 다른 경우가 많기 때문에 이것은 중요합니다. 공장을 전문화하는 기회를 갖는 것이 유익 할 수 있습니다. 하지만 이제는 정적 인 팩토리를 갖는 것이 왜 나쁜 생각인지 알 수 있습니다. 정적은 확장 될 수 없습니다.

    +1

    테스트 유닛 경험이 많은 숙련 된 개발자는 두 옵션이 모두 나쁜 것임을 알고 있습니다. :)IMHO, 게으른 get보다는 constructor injection을하는 것이 낫다. 왜냐하면 "마법 의존"을 조롱하고 예방하기가 더 쉽기 때문이다. +1 btw. – Fendy

    +0

    @Fendy - 당신은 생성자에 대해 옳습니다. 내가 따르는 일반 규칙은 필수 매개 변수에 생성자 삽입을 사용하고 선택적 매개 변수에 속성 ​​주입을 사용하는 것입니다. 게으른 get은 너무 자주 오용됩니다. 나는 그것을 단지 속성 오버라이드의 패턴으로 사용한다. 위의 예에서 속성은 일반적으로 변경되지 않는 기본 구현을가집니다. 한 번만 (예 : 단위 테스트에서) 다른 구현으로 변경합니다. 속임수는이 질문에 있습니다 : 속성 값을 변경하면 코드가 깨지는 것입니까? YES는 하드 코딩을 의미합니다. NO는 IoC 컨테이너가 올바른 방법이라는 것을 의미합니다. –

    +1

    '코드를 해독 할 속성 값을 변경하는 경우'는 구현을 수정해야한다는 것을 의미하며 기본값을 하드 코드하지 않습니다. 'Lazy' 속성의 단점은 변경해야 할 경우 (DefaultFactory) 모든 곳에서해야한다는 것입니다. Thoug는 걱정하지 마십시오.이 경우에는 적용되지 않을 수도 있지만 다른 경우에는 발생할 수 있습니다. 코드 악용은 쉽습니다. – Fendy

    1

    두 예제 모두 서비스 로케이터 패턴의 변형입니다. 논쟁의 여지가 있지만, 이것을 사용하는 클래스의 의존성이 소비자에게 보이지 않기 때문에 이것은 종종 안티 패턴으로 간주됩니다.

    종속성을 더 명백하게 만드는 방법은 첫 번째 예제와 비슷한 솔루션을 채택하는 것이지만 CreateNew()을 정적 메서드가 아닌 인스턴스 메서드로 만듭니다.

    관련 문제