使用类层次结构重载 - 大多数派生不使用

Lee*_*Lee 6 c# overloading class-hierarchy

问题

我试图避免代码如下所示:

If(object Is Man)
  Return Image("Man")
ElseIf(object Is Woman)
  Return Image("Woman")
Else
  Return Image("Unknown Object")
Run Code Online (Sandbox Code Playgroud)

我认为我可以通过方法重载来实现这一点,但它总是选择最少的派生类型,我认为这是因为重载是在编译时确定的(与重写不同),因此只能在以下代码中假设基类:

代码结构:

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)
Run Code Online (Sandbox Code Playgroud)

代码实现(关键类):

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

我的场景: 基本上我正在创建一个游戏,并希望将现实世界的类(例如男人)与屏幕上的类(一个人的图像)分离.现实世界的对象应该不知道它的屏幕表示,表示将需要知道真实的对象(知道这个人有多大,因此绘制了多少皱纹).我希望有一个后备,如果一个RealObject是一个未知的类型,它仍然显示一些东西(如一个大红十字).

请注意,此代码不是我正在使用的,它是一个简化版本,以保持问题清晰.如果适用,我可能需要稍后添加详细信息,我希望此代码的解决方案也可以在应用程序中使用.

解决这个问题最优雅的方法是什么? - 没有RealObject本身保存有关如何表示它的信息.XNA游戏是一个非常重的AI概念证明,如果它证明是可行的,将从2D改为3D(可能支持低端计算机).

jga*_*fin 4

使用工厂:

public class ImageFactory
{
    Dictionary<Type, Func<IPerson, Image>> _creators;

    void Assign<TPerson>(Func<IPerson, Image> imageCreator) where T : IPerson
    {
       _creators.Add(typeof(TPerson), imageCreator);
    }

   void Create(Person person)
   {
       Func<IPerson, Image> creator;
       if (!_creators.TryGetValue(person.GetType(), out creator))
          return null;

       return creator(person);
   }
}
Run Code Online (Sandbox Code Playgroud)

分配工厂方法:

imageFactory.Assign<Man>(person => new Image("Man");
imageFactory.Assign<Woman>(person => new Image("Big bad mommy");
imageFactory.Assign<Mice>(person => new Image("Tiny little mouse");
Run Code Online (Sandbox Code Playgroud)

并使用它:

var imageOfSomeone = imageFactory.Create(man);
var imageOfSomeone2 = imageFactory.Create(woman);
var imageOfSomeone3 = imageFactory.Create(mice);
Run Code Online (Sandbox Code Playgroud)

为了能够为男性返回不同的图像,您可以使用一个条件:

factory.Assign<Man>(person => person.Age > 10 ? new Image("Man") : new Image("Boy"));
Run Code Online (Sandbox Code Playgroud)

为了清楚起见,您可以将所有更复杂的方法添加到类中:

public static class PersonImageBuilders
{
    public static Image CreateMen(IPerson person)
    {
        if (person.Age > 60)
            return new Image("Old and gready!");
        else
            return new Image("Young and foolish!");

    }
}
Run Code Online (Sandbox Code Playgroud)

并分配方法

imageFactory.Assign<Man>(PersonImageBuilders.CreateMen);
Run Code Online (Sandbox Code Playgroud)