Обобщить метод класса, который выполняет несколько разные действия в зависимости от условия - PullRequest
2 голосов
/ 05 февраля 2020

У меня есть упрощенный класс Animal, который может выполнять food_routine, в котором действия различаются в зависимости от типа животного:

DOG = 'dog'
CAT = 'cat'

class Animal(object):
    def __init__(self, animal_type):
        if animal_type not in [CAT, DOG]:
            raise Exception('unexpected animal')
        self.animal_type = animal_type

    def food_routine(self):
        self.come_to_plate()  # common code
        self.sniff_food()  # common code

        if self.animal_type == CAT:
            self.go_around_plate()

        self.eat_the_food()  # common code

        if self.animal_type == DOG:  # condition I want to avoid
            self.thank_owner()

        self.go_away_from_plate()  # common code

        # cats and dogs do different things after eating:
        if self.animal_type == CAT:  # condition I want to avoid
            self.go_lie_on_couch()
        elif self.animal_type == DOG:  # condition I want to avoid
            self.ask_for_walk_outside()

        self.sleep()  # common code

    def sleep(self):
        print 'sleep'  # common code

    def ask_for_walk_outside(self):
        print 'ask for a walk outside'

    def go_lie_on_couch(self):
        print 'go lie on couch'

    def go_away_from_plate(self):
        print 'go away from plate'  # common code

    def thank_owner(self):
        print 'thank owner'  # only dogs thank owner

    def eat_the_food(self):
        print 'eat the food'  # common code

    def go_around_plate(self):
        print 'go around plate'

    def sniff_food(self):
        print 'sniff food'  # common code

    def come_to_plate(self):
        print 'come to plate'  # common code

Моя проблема заключается в операторах if, которые делают Код не читается. Я попытался решить эту проблему, создав два класса: один для собак и один для кошек. Каждое животное делает только то, что ему известно, в food_routine (и убрал метод из Animal):

class Cat(Animal):
    def food_routine(self):
        self.come_to_plate()  # common code
        self.sniff_food()  # common code
        self.go_around_plate()
        self.eat_the_food()  # common code
        self.go_away_from_plate()  # common code
        self.go_lie_on_couch()
        self.sleep()  # common code


class Dog(Animal):
    def food_routine(self):
        self.come_to_plate()  # common code
        self.sniff_food()  # common code
        self.eat_the_food()  # common code
        self.thank_owner()
        self.go_away_from_plate()  # common code
        self.ask_for_walk_outside()
        self.sleep()  # common code

Это приводит к дублированию кода (common code строк), которого я хочу избежать.

Итак, мой вопрос: что является хорошей практикой, позволяющей избегать дублирования кода, а также избегать операторов if, чтобы код был читабельным и простым?

Ответы [ 2 ]

2 голосов
/ 05 февраля 2020

food_routine должен быть взаимным.

Разделите ваши действия на фазы - «предварительное действие», «действие», «последующее действие». Каждый класс должен реализовывать функции «pre action» и «post action», а класс Animal должен содержать весь общий код. Каждая собака / кошка должны вызывать супер "pre" и "post", чтобы избежать дублирования кода.

class Animal(object):
    .
    .
    .
    def action():
        self.eat_the_food()  # common code

    def pre_action():
        self.come_to_plate()  # common code
        self.sniff_food()  # common code

    def post_action():
        self.go_away_from_plate()  # common code
        self.sleep()  # common code


class Cat(Animal):
    .
    .
    def pre_action():
        super().pre_action()
        self.go_around_plate()


class Dog(Animal)
    .
    .
    .
    def post_action():
        self.thank_owner()
        self.ask_for_walk_outside()
        self.super().post_action()

И затем каждый вызов может быть:

Dog.pre_action()
Dog.action()
Dog.post_action()
2 голосов
/ 05 февраля 2020

Как насчет:

def food_routine(self):
    self.come_to_plate()  # common code
    self.sniff_food()  # common code

    self._pre_eat_action()

    self.eat_the_food()  # common code

    self._post_eat_action()

    self.go_away_from_plate()  # common code

    self._post_leave_plate_action()

    self.sleep()  # common code

Затем реализуйте _pre_eat_action, _post_eat_action и _post_leave_plate_action в Dog и Cat для обработки двух различных вариантов поведения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...