Фабричный метод - Java против Python - PullRequest
0 голосов
/ 14 января 2019

У меня есть вопрос относительно реализации Factory Method в Java и Python.

Предположим, я хочу смоделировать 2 вида животных - собак и кошек и раскрыть фабричный метод их создания.

Как я понял, лучшая практика реализации на Java будет:

abstract class Animal{
   public abstract void sound();
}

public class Dog extends Animal{
   public void sound(){
    System.out.println("Woof");
   }
}

public class Cat extends Animal{
   public void sound(){
    System.out.println("Maw");
   }
}

class AnimalFactory {

   //use getShape method to get object of type shape 
   public Animal getAnimal(String animalType){
      if(shapeType == null){
         return null;
      }     
      if(animalType.equalsIgnoreCase("Dog")){
         return new Dog();
      } else if(animalType.equalsIgnoreCase("Cat")){
         return new Cat();
      } 
      return null;
   }
}

Однако на Python это будет что-то вроде этого ( source ):

class Animal(ABC):
   @abstractmethod
   def sound():
        pass

class Dog(Animal):
   def sound():
       print('Woof')

class Cat(Animal):
   def sound():
       print('Maw')

class AnimalFactory():
   @staticmethod
   def getAnimal(typ):
      targetclass = typ.capitalize()
      return globals()[targetclass]()

На мой вопрос:

Кажется, что, поскольку я использую globals() на Python, я могу фактически использовать AnimalFactory в Python для создания любого произвольного класса, который в таблице символов во время выполнения, который принимает нулевые аргументы, в отличие от реализации Java который явно проверяет имя класса.

Это плохая практика или просто "питонский путь"?

Спасибо.

Edit:

Я хочу уточнить, почему я не чувствую себя комфортно с кодом Python:

Предположим, я хочу написать другой класс Factory для другой группы классов, он будет иметь ту же реализацию, что и Animal, и теоретически я мог бы даже использовать точный класс Factory.

Я знаю, что могу рассердить некоторых людей из-за следующего утверждения, но я чувствую, что поведение 'утиной типизации' и отсутствие формального явного контракта в коде являются корнем проиллюстрированной проблемы и болезней Python в большие девелоперские проекты.

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Если это просто «для вашего собственного использования», то я, вероятно, не буду слишком обеспокоен. Однако, если это интерфейс, который будут использовать «другие люди», то, на мой взгляд, то, что называет себя AnimalFactory, не имеет смысла возвращать что-то, что не является Animal. Итак, я думаю, что проверка должна быть сделана.

Я бы предположил, что простой способ сделать это - убедиться, что результат вызова globals()[targetclass]() является экземпляром Animal.

0 голосов
/ 15 января 2019

Ну, это не кажется плохой практикой для меня. Тем не менее, я сначала проверил бы, существует ли такой targetClass, поэтому я не получу сообщение об ошибке.

Плюс, я уверен, что есть много способов сделать метод фабрики Java более эффективным. например Я мог бы заранее создать список всех классов, расширяющих Animal, затем, когда я получу переменную animalType, я мог бы найти из списка класс, соответствующий этому типу.

Есть много способов и библиотек, которые помогают получить такой список. Один из популярных вариантов - Reflections , который вы можете использовать следующим образом:

Reflections reflections = new Reflections("my.project");
Set<Class<? extends Animal>> classes = reflections.getSubTypesOf(Animal.class);

Тогда просто пройдитесь по набору и выберите нужный класс.

Edit:

Что касается ваших правок, я бы не назвал это болезнью. Возможности Python великолепны, но иногда есть функции типа «Вы можете, но это не значит, что вы должны», я думаю, это одна из них. Вы можете определить для каждой фабрики набор «юридических классов», которые вы можете создать на этой конкретной фабрике - такая практика может немного снизить ваши опасения :)

...