我有一个生态系统模拟,动物相互移动和碰撞。下面是我处理碰撞的方法:
public void HandleCollisionBetween(Animal a, Animal b)
{
if (a.GetType().Name == b.GetType().Name) { // same type collision
bool fishCollision = a.GetType().Name == typeof(Fish).Name;
if (fishCollision) {
AddAnimal(new Fish());
}
}
else { // bear-fish collision
Bear bear = a.GetType() == typeof(Bear) ? a as Bear : b as Bear;
Fish fish = a.GetType() == typeof(Fish) ? a as Fish : b as Fish;
bear.Eat(fish);
RemoveAnimal(fish);
}
}这段代码是我生态系统类的一部分。有人建议我将这段代码作为一个单独的类,实现一个接口,然后使用它。这样它就可以测试了。问题是:当两种动物发生碰撞时,我需要添加或移除生态系统中的动物。我所能想到的就是:
interface ICollisionHandler {
void HandleCollisionBetween(Animal a, Animal b, Ecosystem ecosystem);
}但是这个关于生态系统的说法是不对的。我非常感谢任何能帮助我改进这类事情的帮助和信息。
发布于 2019-11-15 16:09:23
所以一开始,我发现当你交叉比较很多类的时候,一种方法是备份并问问自己,你写的类是否应该重新组合成数据,而不是类,至少在你的应用程序中它们相交的接触点是这样的。因此,首先,我将给出一个示例,将熊/鱼类缩减为一个基类,动物,并将熊或fosh的详细信息打包为数据。但是,您可以进一步研究这个示例,并拥有一个从purpose继承的熊和鱼类,但是为了确定碰撞结果,我不认为将它们作为类增加太多的价值。这是我的积木。
我并不是什么都相信接口的人,但我将给出这个例子,它将问题分解为上面的几个部分:
public class Animal
{
public string Identifier { get; }
public string SpeciesName { get; }
public Animal(string animalName)
{
SpeciesName = animalName;
Identifier = Guid.NewGuid().ToString();
}
}
public class AnimalCollisionResolver
{
public ICollisionResult ResolveCollision(Animal a, Animal b)
{
// Handle the easy case -> reproduction of same species
if (a.SpeciesName == b.SpeciesName)
return new AddNewAnimalCollisionResult { NewAnimalToAdd = new Animal(a.SpeciesName) };
// Handle handle harder case, how to determine which ones eat the others, this will be as complex as you need it
var animals = new[] { a, b };
var names = animals.Select(_ => _.SpeciesName);
// Bear-eats-Fish mapping here
if (names.Contains("Bear") && names.Contains("Fish"))
{
return new RemoveSpecificAnimalCollisionResult
{
IdentifierOfAnimalToRemove = animals.Single(_ => _.SpeciesName == "Fish").Identifier
};
}
throw new NotImplementedException("I need to map out the rest of the collision resolutions here.");
}
}
// This could be an abstract base class and the code would not change, FYI
public interface ICollisionResult { }
public class AddNewAnimalCollisionResult : ICollisionResult
{
public Animal NewAnimalToAdd { get; set; }
}
public class RemoveSpecificAnimalCollisionResult : ICollisionResult
{
public string IdentifierOfAnimalToRemove { get; set; }
}
public class Ecosystem
{
public List<Animal> CurrentAnimals { get; set; }
public AnimalCollisionResolver CollisionResolver { get; set; }
public Ecosystem()
{
// seed the ecosystem here
CurrentAnimals = new List<Animal> {
new Animal("Bear"),
new Animal("Bear"),
new Animal("Fish"),
new Animal("Fish"),
};
CollisionResolver = new AnimalCollisionResolver();
}
public void HandleCollision(Animal a, Animal b)
{
var result = CollisionResolver.ResolveCollision(a, b);
if (result is AddNewAnimalCollisionResult)
{
var addResult = (AddNewAnimalCollisionResult)result;
CurrentAnimals.Add(addResult.NewAnimalToAdd);
}
else if (result is RemoveSpecificAnimalCollisionResult)
{
var removeResult = (RemoveSpecificAnimalCollisionResult)result;
CurrentAnimals = CurrentAnimals.Where(_ => _.Identifier != removeResult.IdentifierOfAnimalToRemove).ToList();
}
else
{
throw new Exception("Unknown ICollisionResult here");
}
PrintOutTheCurrentAnimals();
}
public void PrintOutTheCurrentAnimals()
{
foreach (var animal in CurrentAnimals)
Console.WriteLine($"{animal.SpeciesName} {animal.Identifier}");
Console.WriteLine("");
}
}我不知道你是如何声明这些动物的,并决定谁与谁发生碰撞,但这里有一个例子来展示这些基本知识:
var ecoSystem = new Ecosystem();
ecoSystem.PrintOutTheCurrentAnimals();
var allBears = ecoSystem.CurrentAnimals.Where(_ => _.SpeciesName == "Bear");
var bear1 = allBears.Take(1).Single();
var bear2 = allBears.Skip(1).Take(1).Single();
var fish1 = ecoSystem.CurrentAnimals.First(_ => _.SpeciesName == "Fish");
ecoSystem.HandleCollision(bear1, fish1);
ecoSystem.HandleCollision(bear1, bear2);https://softwareengineering.stackexchange.com/questions/401131
复制相似问题