gpt4 book ai didi

c# - 访客模式的实现。小行星/宇宙飞船碰撞问题

转载 作者:行者123 更新时间:2023-11-30 16:26:21 25 4
gpt4 key购买 nike

我尝试学习双重调度和访问者模式,但下面的代码显然是错误的。我一定是遗漏了一些明显的东西,但我不知道如何修复它。谁能照亮我?我不知道如何在访问者中放置具体实例,是否应该在具体访问者类中创建一个构造函数?

interface Collidable
{
void Accept(IVisitor other);
}

class Asteroid : Collidable
{
public void Accept(IVisitor other)
{
Console.Write("[Asteroid] ");
other.visitAsteroid(this);
}
}

class Spaceship : Collidable
{
public void Accept(IVisitor other)
{
Console.Write("[Spaceship] ");
other.visitSpaceship(this);
}
}

interface IVisitor
{
void visitAsteroid(Asteroid a);
void visitSpaceship(Spaceship s);
}

class CollisionWithAsteroidVisitor : IVisitor
{
public void visitAsteroid(Asteroid a)
{
Console.WriteLine("Collided with asteroid");
}

public void visitSpaceship(Spaceship s)
{
Console.WriteLine("Collided with asteroid");
}
}

class CollisionWithSpaceShipVisitor : IVisitor
{
public void visitAsteroid(Asteroid a)
{
Console.WriteLine("Collided with spaceship");
}

public void visitSpaceship(Spaceship s)
{
Console.WriteLine("Collided with spaceship");
}
}

static void Main(string[] args)
{
Asteroid a1 = new Asteroid();
Asteroid a2 = new Asteroid();
Spaceship s1 = new Spaceship();
Spaceship s2 = new Spaceship();

s1.Accept(new CollisionWithAsteroidVisitor()); // this must be wrong
s1.Accept(new CollisionWithSpaceShipVisitor()); // this must be wrong
}

最佳答案

据我了解,您希望实现不同的对象可以相互碰撞,并且当发生此类碰撞时,参与者将知道他们碰撞到了其他类型的对象。

要在不使用反射(或如您所说的 RTTI,尽管它是 C++ 术语)的情况下实现此目的,使用访问者模式是一种很好的方法。您做错了什么,在这种情况下,两个对象都将充当接受者和访问者,具体取决于哪个对象与哪个对象发生碰撞。我们正在碰撞的对象将成为接受者(“接受碰撞对象”),而正在碰撞另一个对象的对象将成为访问者(“访问/碰撞到接受者对象)。

当碰撞物体是另一个物体时,接受者-访问者的角色可能会颠倒(移动的小行星碰撞到宇宙飞船与移动的宇宙飞船碰撞到静止的小行星)。从这个例子中你可以看到,一个对象可以根据情况充当接受者或访问者。这必须反射(reflect)在类层次结构中,因此两个对象都必须实现 ICollidable 和 IVisitor 接口(interface)。

我重写了您发布的代码,因此 Asteroid 和 Spaceship 类都实现了这两个接口(interface)。不再需要额外的访问者类,因为我们的对象本身成为了访问者:

interface ICollidable
{
void Accept(IVisitor other);
}

interface IVisitor
{
void VisitAsteroid(Asteroid a);
void VisitSpaceship(Spaceship s);
}

class Asteroid : ICollidable, IVisitor
{
public void Accept(IVisitor other)
{
Console.Write("[Asteroid] ");
other.VisitAsteroid(this);
}

public void VisitAsteroid(Asteroid a)
{
Console.WriteLine("Collided with asteroid");
}

public void VisitSpaceship(Spaceship s)
{
Console.WriteLine("Collided with asteroid");
}
}

class Spaceship : ICollidable, IVisitor
{
public void Accept(IVisitor other)
{
Console.Write("[Spaceship] ");
other.VisitSpaceship(this);
}

public void VisitAsteroid(Asteroid a)
{
Console.WriteLine("Collided with spaceship");
}

public void VisitSpaceship(Spaceship s)
{
Console.WriteLine("Collided with spaceship");
}
}


class Main
{
public static void Main(string[] args)
{
Asteroid a1 = new Asteroid();
Asteroid a2 = new Asteroid();
Spaceship s1 = new Spaceship();
Spaceship s2 = new Spaceship();

s1.Accept(a1);
s1.Accept(as);
a1.Accept(s1);
a2.Accept(a2);
}
}

如果您运行该程序,您将在控制台中获得以下输出:

[Spaceship] Collided with asteroid
[Spaceship] Collided with spaceship
[Asteroid] Collided with spaceship
[Asteroid] Collided with asteroid

我希望它让您明白如何在这种情况下使用访问者模式。

关于c# - 访客模式的实现。小行星/宇宙飞船碰撞问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8869767/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com