使用类层次结构重载 - 大多数派生未使用
问题
我试图避免如下所示的代码:
If(object Is Man)
Return Image("Man")
ElseIf(object Is Woman)
Return Image("Woman")
Else
Return Image("Unknown Object")
我认为我可以通过方法重载来做到这一点,但它总是选择最少派生的类型,我认为这是因为重载是在确定的编译时(与重写不同),因此在以下代码中只能假定基类:
代码结构:
NS:Real
RealWorld (Contains a collection of all the RealObjects)
RealObject
Person
Man
Woman
NS:Virtual
VirtualWorld (Holds a reference to the RealWorld, and is responsible for rendering)
Image (The actual representation of the RealWorldObject, could also be a mesh..)
ArtManager (Decides how an object is to be represented)
代码实现(关键类):
class VirtualWorld
{
private RealWorld _world;
public VirtualWorld(RealWorld world)
{
_world = world;
}
public void Render()
{
foreach (RealObject o in _world.Objects)
{
Image img = ArtManager.GetImageForObject(o);
img.Render();
}
}
}
static class ArtManager
{
public static Image GetImageForObject(RealObject obj)// This is always used
{
Image img = new Image("Unknown object");
return img;
}
public static Image GetImageForObject(Man man)
{
if(man.Age < 18)
return new Image("Image of Boy");
else
return new Image("Image of Man");
}
public static Image GetImageForObject(Woman woman)
{
if (woman.Age < 70)
return new Image("Image of Woman");
else
return new Image("Image of Granny");
}
}
我的场景: 本质上,我正在创建一个游戏,并且想要将现实世界的类(例如男人)与屏幕上的类(人的图像)分离。现实世界的对象不应该知道它在屏幕上的表示,该表示需要知道真实的对象(知道这个人有多大,因此画了多少皱纹)。我想要后备,如果 RealObject 是未知类型,它仍然显示一些内容(例如大红十字)。
请注意,此代码不是我正在使用的代码,它是一个简化版本,以保持问题清晰。如果适用的话,我可能需要稍后添加详细信息,我希望此代码的解决方案也适用于应用程序。
解决这个问题最优雅的方法是什么? - RealObject 本身没有保存有关如何表示它的信息。 XNA 游戏是一个概念验证,人工智能含量很高,如果证明可行,将从 2D 更改为 3D(可能支持低端计算机)。
The problem
I am trying to avoid code that looks like the following:
If(object Is Man)
Return Image("Man")
ElseIf(object Is Woman)
Return Image("Woman")
Else
Return Image("Unknown Object")
I thought I could do this through method overloading, but it always picks the least derived type, I assume this is because the overloading is determined at compile time (unlike overriding), and therefore only the base class can be assumed in the following code:
Code structure:
NS:Real
RealWorld (Contains a collection of all the RealObjects)
RealObject
Person
Man
Woman
NS:Virtual
VirtualWorld (Holds a reference to the RealWorld, and is responsible for rendering)
Image (The actual representation of the RealWorldObject, could also be a mesh..)
ArtManager (Decides how an object is to be represented)
Code Implementation (key classes):
class VirtualWorld
{
private RealWorld _world;
public VirtualWorld(RealWorld world)
{
_world = world;
}
public void Render()
{
foreach (RealObject o in _world.Objects)
{
Image img = ArtManager.GetImageForObject(o);
img.Render();
}
}
}
static class ArtManager
{
public static Image GetImageForObject(RealObject obj)// This is always used
{
Image img = new Image("Unknown object");
return img;
}
public static Image GetImageForObject(Man man)
{
if(man.Age < 18)
return new Image("Image of Boy");
else
return new Image("Image of Man");
}
public static Image GetImageForObject(Woman woman)
{
if (woman.Age < 70)
return new Image("Image of Woman");
else
return new Image("Image of Granny");
}
}
My scenario:
Essentially I am creating a game, and want to decouple real-world classes (such as a man), from on-screen classes (an image of a person). The real world object should have no knowledge of it's on-screen representation, the representation will need to be aware of the real object (to know how old the man is, and therefore how many wrinkles are drawn). I want to have the fallback where if a RealObject is of an unknown type, it still displays something (like a big red cross).
Please note that this code is not what i'm using, it's a simplified version to keep the question clear. I may need to add details later if applicable, I'm hoping the solution to this code will also work in the application.
What's the most elegant way to solve this? - Without the RealObject itself holding information on how it should be represented. The XNA game is a proof of concept which is very AI heavy, and if it proves doable, will be changed from 2D to 3D (probably supporting both for lower end computers).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用工厂:
分配工厂方法:
并使用它:
为了能够为男性返回不同的图像,您可以使用条件:
为了清楚起见,您可以将所有更复杂的方法添加到类中:
并分配该方法
Use a factory:
Assign factory methods:
And use it:
To be able to return different images for men you can use a condition:
For clarity you can add all more complex methods to a class:
And assign the method
如果您使用的是 .NET 4,请尝试以下操作:
通过强制转换为动态,将在运行时确定实际类型,这将导致调用正确的重载。
If you are using .NET 4, try the following:
By casting to dynamic, the actual type will be determined at runtime, which should then cause the correct overload to be called.
您可以创建接受现实世界对象作为构造函数参数的 Facade 类(即 ManFacade、WomanFacade 等)
You could create Facade classes that accept your real-world object as a constructor argument (ie ManFacade, WomanFacade, etc.)
我相信调用最少派生类的原因是因为您正在外部类中完成工作。如果将 GetImage() 方法设置为 RealObject 类的虚拟成员,则应该调用最派生的版本。请注意,如果需要,您可以将 GetImage() 委托给 ArtManager。
但@seairth 的解决方案完成了同样的事情,并且可能不会那么具有侵入性。
有人可能会说,将 GetImage() 放在 RealObject 类中违反了单一职责……我认为这取决于类的其余部分的外观。但在我看来,RealWorld.Render 不应该负责获取每个 RealObject 的图像。事实上,每次添加 RealObject 的子类时都必须触摸 ArtManager,这违反了 Open/Closed。
I believe the reason the least derived class is being called is because you're doing the work in an external class. If you make the GetImage() method a virtual member of the RealObject class then the most-derived version should get called. Note that you can have GetImage() delegate to the ArtManager if you want.
But @seairth's solution accomplishes the same thing and would probably be less intrusive.
One could argue that putting GetImage() in the RealObject class violates Single Responsibility ... I think that would depend on what the rest of the class looks like. But it seems to me that RealWorld.Render shouldn't be responsible for obtaining the images for each RealObject. And as it is, you'd have to touch ArtManager each time you add a subclass of RealObject, which violates Open/Closed.
如果
RealWorld
的层次结构稳定,您可以使用Visitor
模式。If the hiearchy of the
RealWorld
is stable you could use theVisitor
pattern.