У вас есть несколько альтернатив.Один из подходов состоит в том, чтобы иметь подклассы AnimalHandler
для каждого типа животных и вручную отсылать к правильному:
public class AnimalHandler
{
public void Pet(Animal animal)
{
if (animal is Cat)
{
this.catHandler.Pet((Cat) animal);
}
else if (animal is Dog)
{
this.dogHandler.Pet((Dog) animal);
}
else
{
throw new ArgumentOutOfRangeException("animal");
}
}
private readonly CatHandler catHandler;
private readonly DogHandler dogHandgler;
}
В качестве альтернативы всем «если» и «есть», вы можете добавить AnimalType
Перечислите свойство класса Animal
и используйте оператор switch
.
Приведенный выше подход можно сделать несколько более общим и расширяемым, если создать интерфейс для представления обработчика определенного типа животного:
public enum AnimalType
{
Cat,
Dog,
}
public interface ISpecificAnimalHandler
{
AnimalType AnimalType { get; }
void Pet(Animal animal);
}
public class AnimalHandler
{
public AnimalHandler()
{
var handlers = new ISpecificAnimalHandler[] { new CatHandler(), new DogHandler() };
this.handlersByAnimal = handlers.ToDictionary(handler => handler.AnimalType, handler);
// ...
}
public void Pet(Animal animal)
{
ISpecificAnimalHandler handler;
if (!this.handlersByAnimalType.TryGet(animal.AnimalType, out handler))
{
throw new ArgumentOutOfRangeException("Animal of type " + animal.GetType().Name " not supported.");
}
handler.Pet(animal);
}
private IDictionary<AnimalType, ISpecificAnimalHandler> handlerByAnimalType;
}
public class CatHandler : ISpecificAnimalHandler
{
public AnimalType AnimalType
{
get { return AnimalType.Cat;
}
public void Pet(Animal animal)
{
var cat = (Cat) animal;
// do petting, meow
}
}
Другой, другой, вариант - использовать динамическую отправку:
public class AnimalHandler
{
public void Pet(Animal animal)
{
PetAnimal((dynamic) animal); // will dispatch to most appropriate method at runtime
}
public void PetAnimal(Cat cat)
{
// do petting, meow
}
public void PetAnimal(Dog dog)
{
// do petting, woof
}
}