2011-09-28 69 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