2011-09-28 118 views
4

我甚至不確定要搜索什麼關於這個問題,所以我想我會在這裏發佈。這是動態類還是...?

比方說,我有一大堆的接口等...

/// <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> 
/// 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> 
/// 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)) 

從本質上講,我想告訴工廠使用哪些接口來構建對象。我有容器有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到這樣的想法,這很酷。我想知道如何創建一個只有屬性的接口的參數,並且屬性只有getter(我認爲這很重要)以及屬性的屬性值,並返回一個實現該接口的對象並具有所有屬性定義的屬性。

例如,

/// <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:如何使用裝飾者?

從我看到的裝飾器中,您可以擴展對象的功能。這很酷。但是,您必須提前知道如何擴展該功能。你不能任意做這件事。

請考慮我的代碼庫如上,我想使用裝飾器。

我會說:

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

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

編輯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; 
    } 
} 

所以當你D

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 
    } 
} 

我知道這是不是它是如何將實際工作,但足以說明我點試圖製造。我希望對象實現接口的動態組合,併爲設置者設置默認值。

即使我能這樣做有工廠編寫包含代碼的文本文件:

/// <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的任何具體類都可以在調用As時簡單地返回自己。編輯3:

感謝大家的意見。我很高興我發佈了我對模式的無知; D感謝您的澄清!我喜歡這個網站和你所有可愛的人!

+0

爲什麼你不能與做法最終你使用'InterestingObjects.OfType ()'提及? – sll

+0

@sll:我不知道如何製造工廠。這就是問題所在。或者如果這是一個好方法。 – MPavlak

+0

你期望在所有這些接口之間有什麼不同?除了getters? –

回答

0

我不喜歡IMasterInterface概念,但假設你只是使用抽象術語來解決這個問題 - 我可以看到過去的那個。我也有關於使用一個瑣碎的疑問,在你的例子:

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

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

不應該「公主」應爲「somethingthatlikestolooksandconsumegoods」?

除此之外,我認爲過濾接口類型的方法很好。

+0

我相信這樣一種方式(通過爲今天需要的每種獨特組合提供一個新的界面,我的想法是否正確?),您最終可能會遇到「界面炸彈/混亂」問題,並且這將會很難維護時間 – sll

+0

@馬丁克拉克:我不確定你的意思,是否有錯誤?你知道如何在這個例子中創建工廠嗎?我不知道該怎麼做。另外,((公主是......))只是一個評論。調用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#中的裝飾器,只有C++,但我發現它是一個非常有用和靈活的方式轉發。如果你發現自己創建更多專門的類,它們代表'屬性'類的交集,那麼我認爲裝飾者可能會有幫助。

有關此模式的信息,請參閱Decorator Design Pattern in C#。 (併購買並閱讀GoF設計模式書!)

+0

我想到了這一點,但我不想走一堆列表來查看是否包含該屬性。儘管如此,我會仔細觀察一下,看看它不是那麼糟糕。 – MPavlak

+0

+1。我認爲這是你應該採取的方法,你想添加特定的行爲到一個對象。對於公主的工廠將返回具體類型飾EnjoyLookingAtGoodsDecorator和ConsumesGoodsDecorator –

+0

我不認爲裝飾器將工作,因爲我必須提前知道的組合。我需要裝飾者能夠動態地裝飾任何接口組合。 – MPavlak

0

回答關於工廠的問題,您可以使用反射和/或原型模式來完成,但前提是接口組合是唯一的。如果你有多個具體的類可以滿足請求的接口列表(比如Pricess和Prince類),那麼工廠就無法知道要創建哪個接口。

如果沒有具體的類,並且您真的試圖在運行時創建/編寫/等對象,那麼這是一匹不同顏色的馬。你可能需要一個通用的基類(或者在你的主接口中支持)來輔助(使用另一個海報)裝飾器方法,或者使用方面模式。

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並將其設置爲null,那麼爲什麼不具有實現IMasterInterface的類,並且具有4個具有不同接口(組合)的屬性。仍然是很難找出沒有上下文

HTH

+0

美麗。謝謝。沒有我看到的例子有這樣的任何實現,現在我看到這一切都非常糟糕。 :D – MPavlak

+0

@ user652688檢查更新後的答案,這是你的意思嗎? –

+0

我不想要一個主接口和所有定義的方法,並且在使用未在其上定義的方法時拋出實現類。我有一組非常重疊的界面,但是當它們結合時,行爲會延長。舉例來說,我可以有IProduceGoods {串WhatIProduce {獲得;}雙HowManyPoundsIProduce {獲得;}詮釋EverySoManyDays {獲得;}}和IConsumeGoods {串WhatIConsume {獲得;}雙HowMuchIPayPerPound {獲得;}}然後,兩者的結合有含義。讓所有類具有所有這些屬性是沒有意義的。 – MPavlak