views:

64

answers:

3

I have a utility class library I am writing. A have written a factory class that is generic enough that with a few delegates passed in from the caller it can be reused in many different situations. However, one of my colleagues suggested that I use an abstract class or an interface so it is more explicit what functions needed to be overridden. In the model I have created to use the library you would then need to override 2 classes instead of just one. What criteria determines when it is appropriate to use delegate functions or interfaces.

Using a delegate pattern.


Class A 
{
    Func<string , ReultClass> fun1 {get;set;}

    FactoryObj CreateObj()
    {
         return fun1("")
    }
}

Using an interface pattern

Class B 
{
    InterfaceObj{get;set;}

    FactoryObj CreateObj()
    {
         return InterfaceObj.fun1("")
    }
}
A: 

I would think you would want to change the signature of the method. Instead of making the delegate a property on your class, make that a parameter you need to pass in. Then, you can't even invoke your CreateObj method without passing in the required data, and the signature itself tells you what you need to pass for the method call to be successful.

Tejs
A: 

does/should the factory know about the various 'concrete' versions? Are there a fixed, relatively low number of specific concrete versions? If yes for either, IMHO the abstract base is a good approach. If the caller should be able to pass in 'arbitrary' code, you could either pass in delegates, or if multiple callers may want to handle/interpret the same data, expose it as events from the base and let the various callers hook up and do their interpretation.

Unfortunately, as SLaks mentions, it kind of depends on the specific situation - it's hard to make any kind of blanket statements - even the above one is likely to be a bad idea in some situations :)

James Manning
+1  A: 

If the design is such that the class depends on another class (even a simple class), I would recommend the interface approach, since the object does have to depend on outside code:

interface IA
{
    ResultClass Fun1(string arg);
}

In this case, you can still use delegates; I usually write my "anonymous" classes (as Microsoft calls them) with explicit interface implementations, so the name of the delegate property is the same as the name of the interface method it implements:

class AnonymousA : IA
{ 
    Func<string, ResultClass> Fun1 { get; set; }
    ResultClass IA.Fun1(string arg) { return this.Fun1(arg); }
} 

If there are generics involved (e.g., IA<ResultClass> and the corresponding AnonymousA<ResultClass>), then it's useful to define a factory class, just to clean up the creation syntax:

static class Anonymous
{
    public static IA<ResultClass> A<ResultClass>(Func<string, ResultClass> fun1)
    { return new AnonymousA<ResultClass> { Fun1 = fun1 }
}
Stephen Cleary