2011-09-28 4 views
4

나는이 문제와 관련하여 무엇을 검색해야할지 모르겠다. 그래서 나는 그것을 여기 게시 할 것이라고 생각했다.동적 클래스 또는 ...의 경우입니까?

/// <summary> 
/// Class to represent a farm which grows and stores crops 
/// </summary> 
class Farm : IProduceGoods, IStoreGoods {/*...*/} 

/// <summary> 
/// Class to represent a merchant who buys goods and stores them 
/// </summary> 
class Merchant : IConsumeGoods, IStoreGoods {/*...*/} 

/// <summary> 
/// Window Shopper represents someone who doesn't buy anything and only looks 
/// </summary> 
class WindowShopper : IEnjoyLookingAtGoods{ /*...*/ } 

이제 난 :

... 지금의 나는 같은 인터페이스의 무리가 있다고

/// <summary> 
/// All interesting classes will implement this interface 
/// </summary> 
interface IMasterInterface {} 

/// <summary> 
/// Interface to represent someone that creates/produces goods 
/// </summary> 
interface IProduceGoods : IMasterInterface { int Prop1 {get;} } 

/// <summary> 
/// Interface to represent someone that buys/consumes goods 
/// </summary> 
interface IConsumeGoods : IMasterInterface { int Prop2 {get;} } 

/// <summary> 
/// Interface to represent someone that stores goods 
/// </summary> 
interface IStoreGoods : IMasterInterface { double Prop3 {get;} string name {get;}} 

/// <summary> 
/// Interface to represent someone that enjoys looking at goods 
/// </summary> 
interface IEnjoyLookingAtGoods : IMasterInterface { int Prop4 {get;} DateTime Prop5 {get;} } 

하자, 뭔가처럼, 나는 오늘 내가 원하는 알고 조합이 내 소수의 수업을 들었지만 기쁘다. 내일은 상인에게 실제로 물건을 사주는 수업을하는 것이 좋지 않을 것이다. 그래서 내 코드로 가서 추가 할 것이다.

/// <summary> 
/// Princesses have lots of money to buy stuff and lots of time to look at stuff 
/// </summary> 
class Princess : IEnjoyLookingAtGoods, IConsumeGoods {/*...*/} 
,

IMasterInterface princess = MyFactory.Create(IEnjoyLookingAtGoods, IEnjoyLookingAtGoodsParameters, IConsumeGoods, IConsumeGoodsParameters) 

/// This should be true 
((princess is IEnjoyLookingAtGoods) && (princess is IConsumeGoods)) 

을 본질적 :3210

는 지금, 나는 내가하고 싶은 무엇

는 공장 (또는 유사한) 일을 가지고 말은 ... 내가 그렇게해야한다고 생각하지 않습니다 개체를 생성하는 데 사용할 인터페이스를 팩토리에 알려야합니다. IMasterInterface의 목록이있는 컨테이너가 있습니다.

/// <summary> 
/// My container class for interesting objects 
/// </summary> 
class InterestingObjectContainer 
{ public ReadOnlyCollection<IMasterInterface> InterestingObjects {get;} } 

여기에 질문의 항목이 있습니다. 모든 흥미로운 클래스가 IMasterInterface를 구현하게 한 이유는 List를 가지고 더 구체적인 인터페이스를 필터로 사용할 수 있기 때문입니다. 아마도 다음은 좀 더 명확하게됩니다

더 특정 인터페이스에 필터링함으로써
/// <summary> 
/// I want to see the net population of producers and get there total production 
/// </summary> 
class ProducerProductionCalculator 
{ 
    // THIS IS WHERE THE MEAT OF THE QUESTION RESIDES! 
    ProductionResults Calculate(InterestingObjectContainer interestingObject) 
    { 
    List<IProduceGoods> producers = interestingObject.InterestingObjects.OfType<IProduceGoods>(); // Perhaps more interest LINQ 
    return DoSomethingWithListToAggregate(producers); 
    } 
} 

, 지금 DoSomethingWithListToAggregate (ICollection은 생산자)에 전달 된 모든 객체 IProduceGoods의 방법을 가지고/속성 믿을 수있는 수업.

사전 및 문자열 속성 조회로 구현하는 방법에 대해 생각했지만 강력하게 형식화 된 코드를 작성하여 어딘가에서 간단한 철자법 실수로 모든 것을 망칠 수없는 것처럼 느꼈습니다.

어쨌든, 나는 요약 추측 :

이 객체에 변수 속성을 구현하는 빈약 한 방법이며 더 나은 것이 무엇 그렇다면. 그렇지 않다면 위에서 설명한대로 공장에서 객체를 만드는 방법이 있습니까?

편집 :

내가이 일을 생각에 몇 가지 OKS를 참조하고 멋지다. 나는 단지 속성을 가진 인터페이스의 인수를 취하는 속성을 가진 팩토리를 만드는 방법을 궁금해했다. 속성은 속성에 대한 속성 값과 함께 getters (나는 중요한 포인트라고 생각한다)를 가지며 인터페이스를 구현하고 모든 속성이 정의되었습니다. 예를 들어

,

/// <summary> 
/// Factory to create any combination of properties 
/// </summary> 
class FactoryForInterestingObjects 
{ 
    public static IMasterInterface Create(
    List<KeyValuePair</*what goes here is the interface that I want to use, 
         what goes here are the parameter values that 
         should be returned by the getter */>>); 
} 

내가 공장을 전달할 것 모든 인터페이스와 그 매개 변수 값과 그 인터페이스를 구현하고 그 값이 어떤 클래스를 만드는 것입니다. 바라건대 이것은 좀 더 명확한가?

편집 2 : Decorator를 사용하는 방법?

데코레이터에 관해서는 객체의 기능을 확장 할 수 있습니다. 멋지다. 그러나 미리 기능을 확장하는 방법을 미리 알아야합니다. 이것을 임의로 할 수는 없습니다.

내 코드 기반이 위와 같고 데코레이터를 사용하려고한다고 가정합니다.

내가 말하고 싶지만 :

// Edited to be correct 
class EnjoyLookingDecorator : IEnjoyLookingAtGoods 
{ 
    private IMasterInterface instance; 
    public EnjoyLookingDecorator(IMasterInterface wrappedObject) 
    { this.instance = wrapped Object;} 

    #region Implementation of IEnjoyLookingAtGoods 
    /*...*/ 
    #endregion 
} 

EDIT 4 :

난 여전히 문제가 해결 거라고 생각하지 않습니다. 귀하의 예제에서, 나는 포함 된 클래스 인터페이스를 잃고, 그것을 리디렉션해야합니다. 예를 들어,

class EnjoyLookingDecorator : IEnjoyLookingAtGoods 
{ 
    private IMasterInterface instance; 
    public EnjoyLookingDecorator(IMasterInterface concrete) 
    { this.instance = concrete;} 

    #region Implementation of IEnjoyLookingAtGoods here 
    /*...*/ 
    #endregion 

    bool Is<T>() //this should be in the IMasterInterface 
    { 
    return this is T or instance is T; 
    } 
} 

class ConsumesGoodsDecorator : IConsumeGoods 
{ 
    private IMasterInterface instance; 
    public ConsumesGoodsDecorator (IMasterInterface concrete) 
    { this.instance = concrete;} 

    #region Implementation of IConsumeGoods here 
    /*...*/ 
    #endregion 

    bool Is<T>() 
    { 
    return this is T or instance is T; 
    } 
} 

그래서 당신이

IMasterInterface princess = new MasterClass() //whatever your concrete type is named 
princess = new ConsumesGoodsDecorator(new EnjoyLookingDecorator(princess)) 

을 거라고 때 당신은 더 이상 모든 속성을 잃게 princess.PropertyOnIEnjoyLookingDecoratorInterface 할 수 없다. 이것은 내가 원하는 것이 아닙니다. 속성을 보존하는 유일한 방법은 리디렉션하는 것입니다.

class ConsumesGoodsDecorator : IConsumeGoods, IEnjoyLookingAtGoods 
{ 
    private IMasterInterface instance; 
    public ConsumesGoodsDecorator (IMasterInterface concrete) 
    { this.instance = concrete;} 

    #region Implementation of IConsumeGoods here 
    /*...*/ 
    #endregion 

    #region Redirect all the IEnjoyLookingAtGoods Property Getters to instance 
    /* ... */ 
    #endregion 

    bool Is<T>() 
    { 
    return this is T or instance is T; 
    } 
} 

리디렉션을 수행하면 인터페이스를 구현해야합니다. 그런 다음 조합에는 모두 코드가 있어야하는데, 이는 피하려고하는 것입니다. 나는 인터페이스의 조합에 제약이 없다.

수정 5 :

아마도 나는 내 질문에 아직 명확하지 않습니다. 그들의 속성이 채워과은 위에 그대로 인터페이스를 상상

을 공장 같은 것을 할 수있는 경우. 내가 실현

/// <summary> 
/// Factory to create any combination of properties 
/// </summary> 
class FactoryForInterestingObjects 
{ 
    public static IMasterInterface Create(
    List<KeyValuePair<Type t, ArgSet customArguments>> interfaces)) 
    { 
    object baseObject; 
    foreach(KeyValuePair<Type, ArgSet> interface in interfaces) 
    { 
     AddInterface(interface, object); 
    } 
    } 

    private static void AddInterface(KeyValuePair<Type, ArgSet> interface, ArgSet arguments) 
    { 
    // Delegate this to someone else 
    if(interface.Key is typeof(IProduceGoods)) 
    { 
     IProduceGoodsExtensions.AddInterface(o, interface.value); 
    } 
    } 
} 

public static class IProduceGoodsExtensions 
{ 
    public static void AddInterface(object o, ArgSet arguments) 
    { 
     // do something to object to make it implement IProductGoods 
     // and make all the getters return the arguments passed in ArgSet 
    } 
} 

를이 실제로 어떻게 작동하는지가 아니라 내가 '점을 보여 나는하려고 애쓰다. 객체가 인터페이스의 동적 조합을 구현하고 setter에 대한 기본값을 갖기를 원합니다.

/// <summary> 
/// Auto Generated by Factory to create a new type on the fly 
/// </summary> 
class ClassImplementingIProduceGoodsAndIEnjoyLookingAtGoods : IProduceGoods, IEnjoyLookingAtGoods 
{ 
    // From IProduceGoods 
    public int Prop1 {get; private set;} 
    // From IEnjoyLookingAtGoods 
    public int Prop4 {get; private set;} 
    public DateTime Prop5 {get; private set;} 
    public ClassImplementingIProduceGoodsAndIEnjoyLookingAtGoods(int prop1, int Prop4 , DateTime Prop5) 
    { 
    this.Prop1 = prop1; this.Prop4 = Prop4; this.Prop5 = Prop5; 
    } 
} 

그런 다음 클래스를 컴파일하고 어떻게 든 내가 그것의 인스턴스를 만들 수 있습니다 : 내가 뭔가를 할 수

경우에도 공장이 코드가 포함 된 텍스트 파일을 작성 가지고있는 것처럼. 그게 내가 원하는거야. 잘하면 그게 더 의미가 있습니다.

편집 6 :

이것은 내가 아마 내가이 시점에서 대안을 확인할 수 없습니다 때문에 같이 갈거야 솔루션입니다.

//Update Master Interface 
interface IMasterInterface 
{ 
    bool Is(Type t); 
    IMasterInterface As(Type t); 
} 

/// <summary> 
/// Class to build up a final object 
/// </summary> 
class CompositionObject : IMasterInterface 
{ 
    ICollection<IMasterInterface> parts; 
    CompositionObject(IMasterInterface object){ parts = new List<IMasterInterface(object);} 
    bool Is(Type t) 
    { 
    foreach(IMasterInterface part in parts) 
    { if (part is t) return true; // not sure on this off top of head 
    } 
     return false; 
    } 

    IMasterInterface As(Type t) 
    { 
    foreach(IMasterInterface part in parts) 
    { if(part is t) return part; } 
    } 

    bool Add(IMasterInterface interface) 
    { this.Is(typeof(interface)) return false; // don't add again 
    this.parts.Add(interface) } 
} 

이제 내 공장에서는 이러한 컴포지션 개체를 반환 할 수 있으며 호출되는 동안 안전하게 다운 캐스트 할 수 있습니다. 캐스팅을 피하기 위해 제네릭을 사용하는 방법이있는 것처럼 느껴집니다.

IMasterInterface를 구현하는 구체적인 클래스는 호출 될 때 단순히 자신을 반환 할 수 있습니다.

편집 3 :

의견을 보내 주셔서 감사합니다.나는 패턴의 나의 무지를 게시했기 때문에 기쁘다, D 명확히 해 주셔서 감사합니다! 나는이 사이트와 당신의 모든 사랑스러운 사람들을 거기에서 사랑한다 !!

+0

없이 파악하기 어렵다? – sll

+0

@sll : 공장 제작 방법을 모르겠습니다. 그게 질문입니다. 또는 이것이 좋은 접근법이라면 말이다. – MPavlak

+0

이 모든 인터페이스간에 어떤 차이가있을 것으로 예상됩니까? 그냥 게터 말고? –

답변

0

IMasterInterface 개념이 맘에 들지 않지만 질문에 추상적 용어 만 사용한다고 가정하면 과거를 볼 수 있습니다. 또한 귀하의 예제에서 사용에 대한 대수롭지 않은 일에 마음 쓰는 의심의 여지가 있습니다

IMasterInterface princess = MyFactory.Create(IEnjoyLookingAtGoods, IEnjoyLookingAtGoodsParameters, IConsumeGoods, IConsumeGoodsParameters) 

/// This should be true 
((princess is IEnjoyLookingAtGoods) && (princess is IConsumeGoods)) 

는 "공주" "somethingthatlikestolooksandconsumegoods"해야하지 않나요?

그 외에도 구현 된 인터페이스의 유형을 필터링하는 방식이 좋다고 생각합니다.

+0

나는 그런 식으로 믿는다 (당신이 오늘 필요로하는 각각의 고유 한 조합을위한 새로운 인터페이스를 도입 함으로서, 내가 생각할 권리가 있는가?) 당신은 "인터페이스 폭탄/혼란"문제로 끝날 수 있고, 이것은 매우 어려운 유지 보수 시간이 될 것이다. – sll

+0

@ Martin Clarke : 네가 무슨 뜻인지 확신 할 수 없어, 실수있어?이 예제에서 팩토리를 만드는 방법을 알고 있습니까? 나는 그것을 어떻게하는지 모른다. 또한, ((공주님은 ...))은 단지 주석이었습니다. Create에 대한 인수 호출의 결과는 사실과 같아야합니다 (코드에서 사용하지 않을 것임) – MPavlak

0

이것은 좋은 방법입니다. 그리고, 솔직히, 나는 그것에 어떤 문제도 보지 않는다. 인터페이스는 단지 인터페이스 일 뿐이며 공통 구성원 세트를 설명하는 방법을 제공합니다. 문제는 귀하의 질문이 매우 일반적이고 성취하려는 것을 이해하기 어렵다는 것입니다.

인터페이스를 받아들이는 팩토리 방식은 상당히 이상합니다. 예를 들어 우리는 다음 코드를 가지고 있습니다 :

public class A : IFoo { } 
public class B : IFoo { } 

var x = MyFactory.Create(IFoo); 

공장은 무엇을 만들 것입니까? A 또는 B의 인스턴스?

어쨌든 나는 최선의 조언을 내놓을 수 있다고 생각합니다. 그것을 지나치게 생각하지 마십시오.

+0

고마워, 제 생각에도 좋은 생각입니다. 요점은 귀하의 예제에서 클래스 A 또는 B를 구현하고 싶지 않다는 것입니다. 공장에서 Foo를 구현하는 클래스를 만들고 Foo 속성의 매개 변수를 전달하겠습니다. 나는 명확하게하기 위해 질문을 갱신 할 것이다. – MPavlak

2

데코레이터 디자인 패턴을 살펴보십시오. 내가 볼 수있는 한, 당신이 염두에두고있는 일련의 속성, 즉 일련의 속성에서 가져온 혼합 속성 집합을 포함 할 수있는 객체를위한 것입니다. Decorator 모델에서 각 속성은 고유 한 클래스이며 이러한 클래스를 효과적으로 연결하여 원하는 속성으로 객체를 만듭니다.

필터링을 구현하려면 일련의 반복기를 사용하여 데코레이터 체인을 걸어서 테스트중인 개체에 대한 데코레이터가 포함되어 있는지 확인해야합니다.

저는 C#에서만 Decorator를 사용하지 않았지만 C++ 만 사용했지만 매우 유용하고 유연한 방법을 발견했습니다. '속성'클래스의 교차를 나타내는 & 더 많은 특수 클래스를 만들면 Decorator가 도움이 될 것이라고 생각합니다.

이 패턴에 대한 정보는 Decorator Design Pattern in C#을 참조하십시오. (그리고 GoF Design Patterns 책을 사서 읽어보십시오!)

+0

나는 그것에 대해 생각했지만 재산이 포함되어 있는지 확인하기 위해 많은리스트를 걷고 싶지 않았습니다. 그러나, 나는 이것을 한 번 봐서 그렇게 나쁘지 않은지 보게 될 것이다. – MPavlak

+0

+1. 나는 이것이 당신이 취해야 할 접근법이라고 생각합니다. 당신은 어떤 행동을 객체에 추가하고 싶습니다. 공주에게 당신의 공장은 EnjoyLookingAtGoodsDecorator 및 ConsumesGoodsDecorator로 장식 된 콘크리트 유형을 반환합니다. –

+0

미리 조합을 알고 있어야하므로 데코레이터가 작동하지 않을 것이라고 생각합니다. 즉시 인터페이스 조합을 장식 할 수 있도록 데코레이터가 필요합니다. – MPavlak

0

질문의 답을 공장에 알려 주면 반향 및/또는 프로토 타입 패턴을 사용하여 수행 할 수 있지만 인터페이스 조합이 유일한 경우에만 가능합니다. 요청 된 인터페이스 목록 (예 : 클래스 Pricess 및 Prince)을 만족시킬 수있는 하나 이상의 구체적인 클래스가있는 경우 팩토리는 만들려는 것을 알 수있는 방법이 없습니다.

구체적인 클래스가없고 런타임에/etc를 작성/작성하려고 시도하는 경우 다른 색상의 말입니다. 데코레이터 방식을 사용하거나 패싯 유형 패턴을 사용하여 (다른 포스터에서 제안한대로)이를 지원하기 위해 일반적인 기본 클래스 (또는 아마도 마스터 인터페이스에서의 지원)가 필요할 것입니다.

2

업데이트를 기반으로하면 데코레이터 패턴을 이해하지 못하는 것 같습니다.

행동에 차이가없고 정적 인 인터페이스 (IenjoyLookingAtGoods, IConsumeGoods 등) 인 것처럼 이것이 가장 좋은 방법인지는 모르겠지만 다음과 같이 구현할 수 있습니다. 속성을 추상 유형에 추가하고 새 인스턴스를 설정하여 만듭니다.

데코레이터이

class EnjoyLookingDecorator : IEnjoyLookingAtGoods 
{ 
    private IMasterInterface instance; 
    public EnjoyLookingDecorator(IMasterInterface concrete) 
    { this.instance = concrete;} 

    #region Implementation of IEnjoyLookingAtGoods here 
    /*...*/ 
    #endregion 

    bool Is<T>() //this should be in the IMasterInterface 
    { 
    return this is T || instance.Is<T>(); 
    } 
} 

class ConsumesGoodsDecorator : IConsumeGoods 
{ 
    private IMasterInterface instance; 
    public ConsumesGoodsDecorator (IMasterInterface concrete) 
    { this.instance = concrete;} 

    #region Implementation of IConsumeGoods here 
    /*...*/ 
    #endregion 

    bool Is<T>() 
    { 
    return this is T || instance.Is<T>(); 
    } 
} 

같은 것을해야하고 모두 구현 뭔가를 얻으려면이 같은 작업을 수행해야합니다

IMasterInterface princess = new MasterClass() //whatever your concrete type is named 
princess = new ConsumesGoodsDecorator(new EnjoyLookingDecorator(princess)) 
var b = princess.Is<IEnjoysLookingAtGoods>() 

편집 - 당신이 그것을 해킹 수 좋아요 :

T As<T>() 
    { 
    return this is T ? this : instance.As<T>(); /*be careful here, the implementation in the concrete class should return null if he is not a T*/ 
    } 

    /*continuing the example above*/ 
    var consumer = princess.As<IConsumesGoods>(); //this is good 
    var producer = princess.As<IProducesGoods>(); //this will return null 

하지만 이것은 가장 심한 것입니다. 광고 귀하의 질문, 가장 그 인터페이스를 이해가 안되는 것 같습니다. 행동을 전혀 추가하지 않습니다. 공주에게 IProduceGoods를 갖고 싶지 않고 IMasterInterface를 구현하는 클래스가없고 다른 인터페이스 (구성)가있는 4 개의 속성이있는 이유를 null로 설정하십시오. 그럼에도 불구하고 당신은 당신이`InterestingObjects.OfType ()`를 사용 언급 한 방법으로 끝낼 수없는 이유 컨텍스트

HTH

+0

아름다운. 감사. 내가 본 것을 보지 못한 어떤 예도 이것들을 구현했다. : D – MPavlak

+0

@ user652688 업데이트 된 답변을 확인하십시오. 무슨 뜻입니까? –

+0

정의 된 모든 메소드가있는 하나의 마스터 인터페이스가 필요없고 정의되지 않은 메소드를 사용할 때 구현 클래스가 throw되는 것을 원하지 않습니다. 필자는 겹쳐지지 않는 매우 잘 정의 된 인터페이스 집합을 가지고 있지만 결합하면 동작이 확장됩니다. 예를 들어, IProduceGoods {string WhatIProduce {get;} 두 번 HowManyPoundsIProduce {get;} int EverySoManyDays {get;}} 및 IConsumeGoods {string WhatIConsume {get;} 두 번 HowMuchIPayPerPound {get;}} 두 조합을 가질 수 있습니다. 의미. 모든 수업에 이러한 모든 속성을 포함시키는 것은 의미가 없습니다. – MPavlak