当使用多态性没有意义时,如何实现特定于类型的功能?
未正确利用 OOP 语言的常见危险信号如下所示:
if (typeof(x) == T1)
{
DoSomethingWithT1(x);
}
else if (typeof(x) == T2)
{
DoSomethingWithT2(x);
}
此类设计问题的标准“修复”是使 T1
和 T2
共享一个接口,通过继承基类型或实现公共接口(以支持它的语言);例如,在 C# 中,解决方案可能是:
public interface IT
{
void DoSomething();
}
但是,有时您希望实现根据对象类型而不同的功能,但该功能不属于该对象的类型;因此,多态性似乎是错误的方法。
例如,考虑提供给定数据块视图的 UI 的情况。假设此视图能够根据所呈现的数据类型呈现各种布局和控件,那么如何在没有一堆 if
/else
的情况下实现这种特定于类型的呈现声明?
由于我希望显而易见的原因,在这种情况下将渲染逻辑放在类型本身中对我来说是一个非常糟糕的决定。另一方面,如果不将数据对象的类型与其视觉呈现耦合起来,我很难看出如何避免 if
/else
场景。
这是一个具体的例子:我正在开发一个交易应用程序,该应用程序对各种市场产品使用许多不同的定价模型。这些不同的模型由继承自公共 PricingModel
基础的类型表示;每种类型都与一组完全不同的参数相关联。当用户想要查看特定定价模型(针对特定产品)的参数时,当前这些参数通过检测模型类型并显示一组适当的控件的表单来显示。我的问题是如何比当前更优雅地实现这一点(使用一个大的 if
/else
块)。
我意识到这可能看起来是一个非常基本的问题;这只是我的知识差距之一(坚实的 OOP 原则?设计模式?常识?),我认为是时候修复了。
A common red flag that an OOP language is not being leveraged properly looks like this:
if (typeof(x) == T1)
{
DoSomethingWithT1(x);
}
else if (typeof(x) == T2)
{
DoSomethingWithT2(x);
}
The standard "fix" for such design issues is to make T1
and T2
both share an interface, either through inheritance of a base type or implementation of a common interface (in languages that support it); for example, in C# a solution might be:
public interface IT
{
void DoSomething();
}
However, sometimes you want to implement functionality that differs based on the type of an object but that functionality does not belong within that object's type; thus polymorphism seems the wrong way to go.
For example, consider the case of a UI that provides a view of a given clump of data. Supposing this view is capable of rendering various layouts and controls depending on the type of data being presented, how would you implement this type-specific rendering without a bunch of if
/else
statements?
For reasons that I hope are obvious, putting the rendering logic in the type itself strikes me as a very bad decision in this case. On the other hand, without coupling the type of data object to its visual presentation I have a hard time seeing how the if
/else
scenario is avoided.
Here's a concrete example: I work on a trading application which utilizes many different pricing models for various market products. These different models are represented by types inheriting from a common PricingModel
base; and each type is associated with a completely different set of parameters. When the user wants to view the parameters for a particular pricing model (for a particular product), currently these are displayed by a form which detects the type of the model and displays an appropriate set of controls. My question is how this could be implemented more elegantly than it is currently (with a big if
/else
block).
I realize this probably seems like a very basic question; it's just one of those gaps in my knowledge (of solid OOP principles? design patterns? common sense?) that I figured it's about time to fix.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我们按类型将此类功能注入(Spring.Net)到字典中。
该字典可以由提供该功能的一种存储库来管理。
作为实现细节,实现者通常知道它所依赖的类型,并且可以自己提供它:
然后将其添加到字典中,如下所示:
备注:恕我直言,了解某些事物不属于类非常重要,即使提供特定于子类型的实现会让生活变得更轻松。
编辑:终于明白了你的具体例子。
它实际上是关于实例化正确的 UI 控件来显示定价模型参数。按照我上面描述的模式应该是可能的。如果您没有用于定价模型的单个 UI 控件,您可以创建它或编写 UI 配置器或类似的东西来设置所需的控件。
We are injecting (Spring.Net) such functionality into dictionaries by type.
This dictionary could be managed by a kind of repository which provides the functionality.
As an implementation detail, the implementor usually knows the type it depends on an can provide it itself:
Then it is added to the dictionary like this:
Remark: IMHO, it is very important to understand that some things do NOT belong into a class, even if providing subtype-specific implementations would make life much easier.
Edit: Finally understood your concrete example.
It is actually about instancing the right UI control to show the pricing models parameters. It should be possible with the pattern I described above. If you don't have a single UI control for a pricing model, you either create it or you write a UI configurer or something like this which sets up the required controls.
您可以使用所描述的通用接口方法和命令模式来触发“功能不属于该对象类型”的方法。我认为这不会违反坚实的 OOP 原则。
you can use common interface approach as you describe and Command pattern to trigger methods with "functionality does not belong within that object's type". I think this won't break solid OOP principles.
您所描述的几乎正是访问者模式的用例。
编辑:对于您的具体示例,您可以像这样应用访问者模式:
现在,当您如果需要显示
PricingModelVisitor
特定子类型的参数的编辑控件,您只需调用它即可为您填充适当的 GUI。
What you described is pretty much exactly the use case for the Visitor Pattern.
EDIT: For your concrete example, you could apply the visitor pattern like this:
now, instead of using a big
if
-else
block when you need to display the edit-controls for the parameters of a specific subtype ofPricingModelVisitor
, you can simply calland it will populate the appropriate GUI for you.