2010-12-21 7 views
4

다음과 같은 팩토리 패턴을 구현 중입니다. 여기C#의 팩토리 패턴 구현

public class FeedFactory 
{ 
    #region Singleton Pattern 
    //.. 
    #endregion 

    private static Feed[] _factory = new Feed[(int)FeedType.Total]; 

    public void RegisterFeed(FeedType feedType,Feed feed) 
    { 
     if (_factory[(int)feedType] == null) 
     { 
      _factory[(int)feedType] = feed; 
     } 
     else 
     { 
      // already registered 
     } 
    } 

    public Feed GetFeed(FeedType feedType) 
    { 
     return _factory[(int)feedType]; 
    } 
} 

Feed는 다른 클래스가 상속되는 추상 클래스입니다. 어떻게 다른 수업을 등록 할 수 있습니까? 그들의 생성자로부터 그것을 할 수 있습니까?

+0

else 절에서 아무 것도하지 않으면 제거하는 것이 가장 좋습니다. 이렇게하면 더 쉽게 읽을 수 있습니다. –

+0

이 답변보기 : http://stackoverflow.com/questions/4387573/can-i-use-attributes-so-my-factory-knows-what-it-can-should-instantiate-without-b/4387761#4387761 – Steven

답변

7

이 공장 패턴이 아니다. 팩토리에는 항상 생성자 논리가 적어도 하나는 new입니다. 그것이 공장의 아이디어입니다. 호출자는 객체가 어떻게 생성되는지 걱정할 필요가 없습니다. 이것은 싱글 톤 저장소입니다.

우선 배열을 사용하는 대신 형식 색인 사전이 있어야합니다.

private static Dictionary<Type, Feed> _singletons = new Dictionary<Type, Feed>(); 

그런 다음 등록 방법이 필요하지 않습니다. 사전 싱글 톤을 검색 할 때 자동으로 채워 져야합니다.

이제 피드 클래스에 인수없는 기본 생성자가 있다고 가정합니다. 그 경우, 추상 클래스 Feed로부터 직접 팩토리 메소드를 구현할 수 있습니다. 상속을 제어 할 수 있기 때문에 여기에 몇 가지 제네릭을 사용합니다.

public abstract class Feed 
{ 
    public static T GetInstance<T>() where T:Feed, new() 
    { 
     T instance = new T(); 
     // TODO: Implement here other initializing behaviour 
     return instance; 
    } 
} 

이제 싱글 톤 저장소로 돌아갑니다. 난 당신이 싱글 작업 할 때 할 수있는 좋은 일이있는 스레드 동작을 포함

public class FeedSingletonRepository 
{ 
    private static readonly object _padlock = new object(); 
    private static Dictionary<Type, Feed> _singletons = new Dictionary<Type, Feed>(); 

    public static T GetFeed<T>() where T:Feed 
    { 
     lock(_padlock) 
     { 
      if (!_singletons.ContainsKey(typeof(T)) 
      { 
       _singletons[typeof(T)] = Feed.GetInstance<T>(); 
      } 
      return (T)_singletons[typeof(T)]; 
     } 
    } 
} 

참고.이제 Feed에서 상속 주어진 유형의 싱글을 얻으려면

(의이 SpecializedFeedType를 호출하자), 당신이해야 할 모든은 다음과 같습니다

var singleton = FeedSingletonRepository.GetFeed<SpecializedFeedType>(); 

또는

SpecializedFeedType singleton = FeedSingletonRepository.GetFeed(); 

인 약간 다른 구문을 가진 같은 줄.

Edit2 : 일부 구문 오류가 변경되었습니다.

+0

'typeof (T) .GetInstance()'를 호출하면'System.Type'이 아닌'GetInstance()'호출이 클래스에서 오는 것이 아닌가? – Aks

+0

예, 인스턴스 유형 배열별로 색인을 생성하고 있습니다. 이 방식으로 관계 유형 => 인스턴스를 얻습니다. 인스턴스는 주어진 유형에 대한 싱글 톤입니다. –

+0

예,'typeof (T)'는 피드 클래스의 인스턴스가 아닌 유형입니다. 그래서'typeof (T) .GetInstance()'는 의미가 없다. – Aks

1

RegisterFeed 메서드를 호출 할 때 Feed 클래스의 구체 인스턴스를 전달해야합니다. 따라서 구체적인 구현을 제공하는 것은 호출자의 책임입니다.

+0

발신자가 피드 유형 중 하나입니까? – Aks

+0

발신자는 무엇이든 될 수 있습니다. RegisterFeed 메서드를 호출하면 Feed의 특정 구현을 전달해야합니다. –

+0

나는'class FeedTypeA : Feed'를 가지고 있다고 말한다. FeedTypeA 안에'FeedTypeA'의 public static 객체를 선언하고 생성자에 레지스터를 넣으면. 그게 효과가 있니? – Aks

6

사이드 노트와 마찬가지로 - 팩토리는 생성을 제한하기위한 것이므로 개체를 만들고 공장에 등록하는 것은 흥미로운 선택입니다. 이 객체는 팩토리가 아닌 객체 저장소입니까? 아니면 내가 본 것보다 클래스에 더 많은 것이 있습니까?

오브젝트 저장소 인 경우 this one과 같은 다른 질문에서 영감을 얻을 수도 있습니다.

+0

어떻게 다른 방법으로 작동합니까? 팩토리가 객체를 생성합니까? – Aks

+1

일반적으로 팩토리는 객체를 생성합니다. 간단한 구현에는 Create 메소드가있는 팩토리 인터페이스가 있고 특정 유형을 생성 할 수있는 팩토리 클래스의 구체적인 구현이 있습니다. 변형이 있지만 중요한 점은 변형이 당신을 위해 처리된다는 것입니다. 또한 재사용을 원한다면 당신이하고있는 일을하고 캐시 할 수도 있지만, 공장과 캐시/저장소 측면을 명확하게 분리하고자 할 수도 있습니다. 그것은 당신이 달성하기를 원하는 것에 달려 있습니다 :) 만약 당신이이 시점에서 탐험을하고 있다면 나는 당신의 목표를 먼저 만족시키는 것을 얻을 것입니다. –

0
class FeedFactory { 


    public IFeedFactory GetFeedFactory(string type) { 
     switch(type) { 
      case "1": return new Feed1(); break; 
      case "2": return new Feed2(); break; 
     } 

    } 

} 

참고 모든 피드는 IFeedFactory 인터페이스를 구현하고 필요한 방법을 구현해야합니다. 클라이언트

FeedFactory ff1 = new FeedFactory(); 
IFeedFactory obj = ff1.GetFeedFactory("1"); 
obj.ExecuteMethod(); 
1

에서

// 그냥 해당 유형의 인스턴스를 만들 수 Activator.CreateInstance를 사용하여 다음 만들려는 클래스의 유형을 등록합니다.

이이 방식으로 작동한다 :

private static Type[] _factory = new Type[(int)FeedType.Total]; 

public void RegisterFeed(FeedType feedType, Type type) 
{ 
    ... 
    _factory[(int)feedType] = type; 
    ... 
} 

public Feed GetFeed(FeedType feedType) 
{ 
    return Activator.CreateInstance(_factory[(int)feedType]) as Feed; 
} 

당신은 다음과 같은 RegisterFeed를 호출 할 수

RegisterFeed(FeedType.SomethingSpecial, typeof(MyDerivedSpecialFeed));