8

好的,所以我正在寻找一些大致如下所示的代码:

void DoSomething(object o)
{
    if (o is Sometype1) { 
    //cast o to Sometype and do something to it
    }
    else if (o is Sometype2) {
    //cast o to Sometype2 and do something to it
    }
    ...
    else if (o is SometypeN) {
    //cast o to SometypeN and do something to it
    }
}

现在一种方法是让所有o用作参数的对象实现一个接口,如

interface ICanHaveSomethingDoneToMe
{
    //expose various properties that the DoSomething method wants to access
}

但问题是我不希望我的所有对象都实现这个接口——do something 方法的逻辑并不真正属于它们。我应该使用什么模式来处理这个问题?

我怀疑类似的一系列实现

interface IPropertiesForDoingSomethingTo<T>
{
    //expose various properties that the DoSomething method wants to access
}

可能会更好。对于我想要执行的每个对象类型,我都有一个实现,但是我遇到了这个新问题。我有时需要一种方法

IPropertiesForDoingSomethingTo<T> GetPropsGeneric(T t);

但这是否需要对其进行大规模切换?我是否应该定义一个带有大量方法的类,例如

IPropertiesForDoingSomethingTo<Someobject1> GetProps(Someobject1 t);
...
IPropertiesForDoingSomethingTo<Someobject1> GetProps(SomeobjectN t);

与无法在运行时添加新类型的通用版本相比,这存在问题。有什么巧妙的方法可以用 GetPropsGeneric 中的 DI 容器来解析容器吗?谢谢!

4

6 回答 6

6

任何时候您看到检查对象类型的 switch 语句(或一系列 if 语句),这都是缺少基类或接口的大红旗。换句话说,代码应该依赖多态性,而不是测试对象类型

如果您无法更改基类或实现接口,您可能会留下一个字典来模拟动态调度。在 C# 中,您可以对包含强制转换的方法使用匿名委托

至于属性访问,如果属性不符合并且不能通过反射访问,您可能需要在上面的方法/委托中提取属性值并将它们传递给通用函数

于 2008-11-20T17:55:15.580 回答
2

看起来您可能正在使用 C#。我相信您可以创建附加到已建立的类的“扩展方法”。

另一种方法是为每种类型创建处理程序委托,并将对委托的引用存储在以对象类型为键的哈希表中。

然后您的“DoSomething”方法可以通过传入的对象类型查找适当的委托并执行。

于 2008-11-20T17:54:17.983 回答
0

一个真实的例子会更有帮助。如果您只是更改一系列相关类的方法的实现,那么正如@Steven A. Lowe 所说,您最好使用多态性并为此使用子类关系。如果类不参与“is a”关系,那么其他模式(如访问者)可能更合适。

于 2008-11-20T18:06:41.030 回答
0

多态是答案,其中传入了一个基础对象。但是,它的样板和语义复杂性可能比您想要的要多得多。

它将要求您的功能以某种方式分流到派生类中,并需要实现“虚拟”功能。

于 2008-11-20T18:07:27.020 回答
0

我认为这对于面向方面的编程方法来说更像是一个问题。

我希望您的 DoSomething 方法将 ICanHaveSomethingDone 接口作为其参数。然后,我将定义 ICanHaveSomethinhgDone 接口,并从中派生实现 DoSomethingToMe 的子类(每个对象一个),每个实现类都不同。它们中的每一个都只需要一个您想要做某事的类型的构造函数,因此当您调用 DoSomething 时,您实际上会调用一个 Factory(非常简单,只需从输入类型创建 ICanHaveSomethingDone 类的实例到创建一个实现 DoSomethingToMe 方法的类的实例,该实例具有底层对象的正确代码。

本质上,这样想;您正在定义一个您希望参数对象实现的接口契约;并以对象的子类和实现特定类的接口行为的特定实现(因此履行合同)的接口的形式定义“装饰”。通过这种方式,您可以使每个类的 DoSomething 方法的实现与这些类的源完全分离。

这样做的另一件事;这意味着如果您将工厂放入 DI 容器中,您可以在运行时添加新类型;通过将您希望能够做某事的新类型注入到您的工厂容器中,只要您将要执行的操作定义为从您的接口和该类派生的类, 你很厉害。如果您实现了完整的 AOP 方法,您甚至可以在运行时定义行为而无需实现派生类;定义你的接口,定义你对动作的行为,并参数化你的派生类的实现,以便在运行时将你想要的行为与你传入的对象组合在一起。但这很复杂...... :-)

顺便说一下,Spring AOP 非常适合这些东西。我会阅读它。

于 2008-11-20T18:09:10.557 回答
0

我同意 Steven 的观点,这个问题上下文也让我想起了双重调度问题,因此访问者模式可能是正确的解决方案。但是,很明显,您的层次结构缺少一些接口定义。

于 2010-04-01T14:07:48.667 回答