// Abstraktní třída definující Factory Method
class AnimalFactory {
  createAnimal() {
    throw new Error("Metoda createAnimal musí být implementována.");
  }
}

// Konkrétní třída implementující Factory Method
class DogFactory extends AnimalFactory {
  createAnimal() {
    return new Dog();
  }
}

class CatFactory extends AnimalFactory {
  createAnimal() {
    return new Cat();
  }
}

// Abstraktní třída reprezentující objekty, které budeme vytvářet
class Animal {
  makeSound() {
    throw new Error("Metoda makeSound musí být implementována.");
  }
}

// Konkrétní třídy reprezentující objekty, které budeme vytvářet
class Dog extends Animal {
  makeSound() {
    console.log("Haf haf!");
  }
}

class Cat extends Animal {
  makeSound() {
    console.log("Mňau mňau!");
  }
}

// Použití Factory Method Pattern
function createAndMakeSound(animalFactory) {
  const animal = animalFactory.createAnimal();
  animal.makeSound();
}

// Použití Factory Method Pattern s různými Factory
const dogFactory = new DogFactory();
const catFactory = new CatFactory();

createAndMakeSound(dogFactory); // Vypíše "Haf haf!"
createAndMakeSound(catFactory); // Vypíše "Mňau mňau!"