I have a class hierarchy as such:
我有一个类层次结构:
+-- VirtualNode
|
INode --+ +-- SiteNode
| |
+-- AbstractNode --+
|
+-- SiteSubNode
And a corresponding NodeCollection
class that is build on INode
. In order to display a NodeCollection
I need to know the final type of each member. So I need a function like this
以及在INode上构建的相应NodeCollection类。为了显示NodeCollection,我需要知道每个成员的最终类型。所以我需要这样的功能
foreach (INode n in myNodeCollection)
{
switch(n.GetType())
{
case(typeof(SiteNode)):
// Display n as SiteNode
}
}
Now, this is really not an object oriented way of doing it. Are there any patterns or recommended ways of doing the same thing, in your opinion?
现在,这实际上不是面向对象的方式。在您看来,是否有任何模式或推荐的方法做同样的事情?
EDIT
I already thought of adding a Display
or Render
method to the INode interface. That has the side effect of coupling the view to the model, which I would really like to avoid.
编辑我已经想过将一个Display或Render方法添加到INode接口。这有将视图耦合到模型的副作用,我真的很想避免。
3 个解决方案
#2
1
When ever you have a select statement using the type of an object, it is a prime candidate for refactoring to polymorphism.
当你有一个使用对象类型的select语句时,它是重构多态的主要候选者。
Check out the book Refactoring by Martin Fowler:
看看Martin Fowler的重构书:
"One of the most obvious symptoms of object-oriented code is its comparative lack of switch (or case) statements. The problem with switch statements is essentially that of duplication. Often you find the same switch statement scattered about a program in different places. If you add a new clause to the switch, you have to find all these switch, statements and change them. The objectoriented notion of polymorphism gives you an elegant way to deal with this problem.
“面向对象代码最明显的症状之一是它相对缺乏switch(或case)语句。switch语句的问题基本上是重复的问题。通常你会发现在不同的地方分散了一个程序的switch语句。如果向交换机添加一个新子句,则必须找到所有这些switch,语句并对其进行更改。面向对象的多态性概念为您提供了一种处理此问题的优雅方法。
Most times you see a switch statement you should consider polymorphism. The issue is where the polymorphism should occur. Often the switch statement switches on a type code. You want the method or class that hosts the type code value. So use Extract Method to extract the switch statement and then Move Method to get it onto the class where the polymorphism is needed. At that point you have to decide whether to Replace Type Code with Subclasses or Replace Type Code with State/Strategy. When you have set up the inheritance structure, you can use Replace Conditional with Polymorphism."
大多数时候你会看到一个switch语句,你应该考虑多态性。问题在于多态性应该发生的地方。通常,switch语句会打开类型代码。您需要承载类型代码值的方法或类。因此,使用Extract Method提取switch语句,然后使用Move Method将其移到需要多态的类上。此时,您必须决定是使用子类替换类型代码还是使用状态/策略替换类型代码。设置继承结构后,可以使用Replace Conditional with Polymorphism。“
Here is one approach to using polymorphism in your situation:
以下是在您的情况下使用多态的一种方法:
-
Define an abstract method in AbstractNode named something like Display().
在AbstractNode中定义一个名为Display()的抽象方法。
-
Then actually implement Display() in each of the SiteNode and SiteSubNode classes.
然后实际在每个SiteNode和SiteSubNode类中实现Display()。
-
Then, when you need to display these nodes, you could simply iterate through a collection containing items of type AbstractNode and call Display() for each.
然后,当您需要显示这些节点时,您可以简单地遍历包含AbstractNode类型的项目的集合,并为每个节点调用Display()。
-
The call to Display() will automatically resolve to the actual concrete implementation for the real type of that item.
对Display()的调用将自动解析为该项的实际类型的实际具体实现。
-
Note: You could also move the Display() method from AbstractNode to the INode interface if VirtualNode is to be displayed.
注意:如果要显示VirtualNode,您还可以将Display()方法从AbstractNode移动到INode接口。
#3
0
If you can change the INode interface - add a virtual method that returns the "view" and override it in the inherited classes.
如果可以更改INode接口 - 添加一个返回“视图”的虚方法,并在继承的类中重写它。
If you can't change the base interface - implement extension methods for each of the classes and have them return the "view" of for each particular class.
如果你不能改变基接口 - 为每个类实现扩展方法,并让它们返回每个特定类的“视图”。
#1
#2
1
When ever you have a select statement using the type of an object, it is a prime candidate for refactoring to polymorphism.
当你有一个使用对象类型的select语句时,它是重构多态的主要候选者。
Check out the book Refactoring by Martin Fowler:
看看Martin Fowler的重构书:
"One of the most obvious symptoms of object-oriented code is its comparative lack of switch (or case) statements. The problem with switch statements is essentially that of duplication. Often you find the same switch statement scattered about a program in different places. If you add a new clause to the switch, you have to find all these switch, statements and change them. The objectoriented notion of polymorphism gives you an elegant way to deal with this problem.
“面向对象代码最明显的症状之一是它相对缺乏switch(或case)语句。switch语句的问题基本上是重复的问题。通常你会发现在不同的地方分散了一个程序的switch语句。如果向交换机添加一个新子句,则必须找到所有这些switch,语句并对其进行更改。面向对象的多态性概念为您提供了一种处理此问题的优雅方法。
Most times you see a switch statement you should consider polymorphism. The issue is where the polymorphism should occur. Often the switch statement switches on a type code. You want the method or class that hosts the type code value. So use Extract Method to extract the switch statement and then Move Method to get it onto the class where the polymorphism is needed. At that point you have to decide whether to Replace Type Code with Subclasses or Replace Type Code with State/Strategy. When you have set up the inheritance structure, you can use Replace Conditional with Polymorphism."
大多数时候你会看到一个switch语句,你应该考虑多态性。问题在于多态性应该发生的地方。通常,switch语句会打开类型代码。您需要承载类型代码值的方法或类。因此,使用Extract Method提取switch语句,然后使用Move Method将其移到需要多态的类上。此时,您必须决定是使用子类替换类型代码还是使用状态/策略替换类型代码。设置继承结构后,可以使用Replace Conditional with Polymorphism。“
Here is one approach to using polymorphism in your situation:
以下是在您的情况下使用多态的一种方法:
-
Define an abstract method in AbstractNode named something like Display().
在AbstractNode中定义一个名为Display()的抽象方法。
-
Then actually implement Display() in each of the SiteNode and SiteSubNode classes.
然后实际在每个SiteNode和SiteSubNode类中实现Display()。
-
Then, when you need to display these nodes, you could simply iterate through a collection containing items of type AbstractNode and call Display() for each.
然后,当您需要显示这些节点时,您可以简单地遍历包含AbstractNode类型的项目的集合,并为每个节点调用Display()。
-
The call to Display() will automatically resolve to the actual concrete implementation for the real type of that item.
对Display()的调用将自动解析为该项的实际类型的实际具体实现。
-
Note: You could also move the Display() method from AbstractNode to the INode interface if VirtualNode is to be displayed.
注意:如果要显示VirtualNode,您还可以将Display()方法从AbstractNode移动到INode接口。
#3
0
If you can change the INode interface - add a virtual method that returns the "view" and override it in the inherited classes.
如果可以更改INode接口 - 添加一个返回“视图”的虚方法,并在继承的类中重写它。
If you can't change the base interface - implement extension methods for each of the classes and have them return the "view" of for each particular class.
如果你不能改变基接口 - 为每个类实现扩展方法,并让它们返回每个特定类的“视图”。