我正在编写一个实用类库。 A编写了一个足够通用的工厂类,从调用者传入的一些代表可以在许多不同的情况下重用它。但是,我的一位同事建议我使用抽象类或接口,以便更明确地需要覆盖哪些函数。在我创建的模型中,您需要使用库来覆盖2个类而不是仅仅一个。什么标准决定何时适合使用委托函数或接口。
使用委托模式。
Class A
{
Func<string , ReultClass> fun1 {get;set;}
FactoryObj CreateObj()
{
return fun1("")
}
}
Class B
{
InterfaceObj{get;set;}
FactoryObj CreateObj()
{
return InterfaceObj.fun1("")
}
}
答案 0 :(得分:1)
我认为你会想要改变方法的签名。不要让委托成为你的类的属性,而是将它作为你需要传入的参数。然后,你甚至不能在不传递所需数据的情况下调用你的CreateObj方法,签名本身会告诉你需要传递什么方法调用成功。
答案 1 :(得分:1)
如果设计是这样的,类依赖于另一个类(甚至是一个简单的类),我会推荐接口方法,因为该对象必须依赖于外部代码:
interface IA
{
ResultClass Fun1(string arg);
}
在这种情况下,您仍然可以使用委托;我通常使用显式接口实现编写我的“匿名”类(如Microsoft称之为),因此delegate属性的名称与它实现的接口方法的名称相同:
class AnonymousA : IA
{
Func<string, ResultClass> Fun1 { get; set; }
ResultClass IA.Fun1(string arg) { return this.Fun1(arg); }
}
如果涉及泛型(例如IA<ResultClass>
和相应的AnonymousA<ResultClass>
),则定义工厂类非常有用,只是为了清理创建语法:
static class Anonymous
{
public static IA<ResultClass> A<ResultClass>(Func<string, ResultClass> fun1)
{ return new AnonymousA<ResultClass> { Fun1 = fun1 }
}
答案 2 :(得分:0)
工厂是否应该知道各种“具体”版本?是否有固定的,相对较少数量的特定混凝土版本?如果是的话,恕我直言,抽象基础是一个很好的方法。如果调用者应该能够传入“任意”代码,您可以传入委托,或者如果多个调用者可能想要处理/解释相同的数据,则将其作为事件从基础公开并让各个调用者挂钩并且做他们的解释。
不幸的是,正如SLaks所提到的那样,这取决于具体情况 - 很难做出任何形式的一揽子陈述 - 即使上述情况在某些情况下也可能是一个坏主意:)
答案 3 :(得分:0)
使用包装类,可以使用接口对代理执行任何操作,反之亦然。要确定哪个适合特定情况,请检查常见的使用模式。
例如,假设有人想在运行时构造一个在处理某个对象时需要执行的操作列表。最常见的操作是在IDisposable类型的对象上调用Dispose,但在某些情况下可能需要执行其他操作(例如,取消订阅事件处理程序)。
一种方法是维护一个MethodInvoker委托列表并依次调用每个委托(*)。如果清理需要在对象上调用Dispose,则为thatObject.Dispose()创建一个新委托并将其添加到列表中。另一种方法是保留IDisposable对象列表,并通过创建一个名为InvokeOnDispose的类来处理其他操作,该类包含一个MethodInvoker,并在调用Dispose时调用它。
前一种方法需要为每个清理操作创建一个新的委托,无论是简单地涉及调用Dispose还是其他东西。在向列表添加IDisposable对象时,后一种方法不需要创建任何新的对象实例,但添加一些其他操作则需要创建除委托之外的InvokeOnDispose对象。
(*)可以简单地使用MulticastDelegate而不是委托列表,但在某些情况下(如对象清理),从一个清理操作抛出的异常可能不应该破坏其他操作。虽然可以使用MulticastDelegate组装清理操作集合,然后使用GetInvocationList在单独的“try-catch”块中运行每个清理操作,但是从一开始就简单地使用委托列表会更容易,更有效。 / p>