Правильное использование абстрактной фабрики C ++ - PullRequest
0 голосов
/ 11 марта 2020

Я не знаю, как исправить использование абстрактной фабрики.
У меня есть пример кода:

#include <iostream>

class Animal {
public:
  virtual void Eat() = 0;
};

class Fish : public Animal {
public:
  /* Overrided method */
  void Eat() override {
    printf("Fish eats..\n");
  }

  /* Only fish's class method */
  void Swim() {
    printf("Fish swims..\n");
  }  
};

class Bird : public Animal {
public:
  /* Overrided method */
  void Eat() override {
    printf("Bird eats..\n");
  }

  /* Only bird's class method */
  void Fly() {
    printf("Bird flies..\n");
  }
};

int main() {
  Animal* fish = new Fish();
  Animal* bird = new Bird();

  Fish* fish_ = reinterpret_cast<Fish*>(fish);
  Bird* bird_ = reinterpret_cast<Bird*>(bird);

  fish_->Eat();
  fish_->Swim();

  bird_->Eat();
  bird_->Fly();

  delete fish;
  delete bird;

  system("pause");
  return 0;
}

В основной функции я создаю объекты Fi sh и Bird, используя интерфейс Animal, и приведите его к указателю Animal, в реальной программе я буду использовать интерфейсы (например, массив с Animals, но мы не знаем, какое это животное).
Fi sh и классы Bird имеют свои собственные методы, класс Animal hasn не так.
Мне нужно вызывать эти методы, но я не правильно использую приведение интерфейса к Fi sh или Bird.
Может быть, есть лучший способ?

1 Ответ

0 голосов
/ 11 марта 2020

Похоже, что вы ищете, это фабрика, которая может возвращать различные уровни доступности API, в зависимости от потребностей вызывающего абонента. Один из способов сделать это - предоставить разные методы-конструкторы, которые возвращают указатели разных типов, как показано в приведенном ниже примере кода. Например, если вызывающему абоненту нужен IBird, он может позвонить createBird(), но если ему на самом деле не нужно звонить Fly() или любым другим вызовам IBird c, он может вместо этого позвонить createAnimal() и получить вернуть IAnimal-указатель, а не IBird-указатель.

// Begin abstract interfaces

class IAnimal
{
public:
   virtual void Eat() = 0;
};

class IBird : public IAnimal
{
public:
   virtual void Fly() = 0;
};

class IFish : public IAnimal
{
public:
   virtual void Swim() = 0;
};

class IAnimalFactory
{
public:
   virtual IAnimal * createAnimal(const std::string & speciesName) = 0;
   virtual IBird * createBird(const std::string & speciesName) = 0;
   virtual IFish * createFish(const std::string & speciesName) = 0;
};

// Begin concrete classes that implement various levels of interface

class Snail : public IAnimal
{
public:
   virtual void Eat() {printf("Snail eats!\n");}
}

class Sparrow : public IBird
{
public:
   virtual void Eat() {printf("Sparrow eats!\n");}
   virtual void Fly() {printf("Sparrow flies!\n");}
};

class Pigeon : public IBird
{
public:
   virtual void Eat() {printf("Pigeon eats!\n");}
   virtual void Fly() {printf("Pigeon flies!\n");}
};

class Tuna : public IFish
{
public:
   virtual void Eat()  {printf("Tuna eats!\n");}
   virtual void Swim() {printf("Tuna swims!\n");}
};

class Marlin : public IFish
{
public:
   virtual void Eat()  {printf("Marlin eats!\n");}
   virtual void Swim() {printf("Marlin swims!\n");}
};

class MyAnimalFactory : public IAnimalFactory
{
public:
   virtual IAnimal * createAnimal(const std::string & speciesName)
   {
           if (speciesName == "snail")   return new Snail;
      else if (speciesName == "sparrow") return new Sparrow;
      else if (speciesName == "pigeon")  return new Pigeon;
      else if (speciesName == "tuna")    return new Tuna;
      else if (speciesName == "marlin")  return new Marlin;
      else                               return NULL;  // unknown animal type!
   }

   virtual IBird * createBird(const std::string & speciesName)
   {
      IAnimal * a = createAnimal(speciesName);
      IBird * b = dynamic_cast<IBird *>(a);
      if (b) return b;
      else
      {
         // Oops, requested animal isn't an IBird!  Caller can't use it
         delete a;
         return NULL;
      }
   }

   virtual IFish * createFish(const std::string & speciesName)
   {
      IAnimal * a = createAnimal(speciesName);
      IFish * f = dynamic_cast<IFish *>(a);
      if (f) return f;
      else
      {
         // Oops, requested animal isn't an IFish!  Caller can't use it
         delete f;
         return NULL;
      }
   }
};
...