Композиция над наследованием

Я отправлюсь с вами в путешествие, чтобы объяснить некоторые принципы проектирования, которые помогут нам организовать, очистить нашу кодовую базу и сделать ее более расширяемой и сопровождаемой. Итак, давайте рассмотрим важные концепции, которые делают наш код более чистым и пригодным для повторного использования.
Что такое композиция и когда мы должны ее использовать?
Позвольте мне объяснить и ответить на этот вопрос на примере, мы все любим примеры 🙂
Представьте, что у вас есть суперкласс под названием Duck

class Duck 
{
    public function fly(){}
    public function quack(){}
    public function display(){}
}
Вход в полноэкранный режим Выйти из полноэкранного режима

У этого класса есть 3 обычных метода, и это хорошо на данный момент, и это хорошо работает для нас, пока ваш клиент не попросит добавить новый тип утки под названием RubberDuck, здесь вы заметите проблему?
Давайте посмотрим на проблему

class RubberDuck extends Duck
{
    public function fly(){} // Why implement this method ?!
    public function quack(){} // also why too ?!
    public function display(){}
}
Вход в полноэкранный режим Выход из полноэкранного режима

Когда вы расширяете родительский класс Duck, вы наследуете методы fly() и Quack(), которые бесполезны для Rubber Duck, так какое же решение? Ответом будет вытащить методы fly и Quack за пределы класса Duck и сделать новый интерфейс под названием что-то вроде FlyableInterface и QuackablInterface, которые оба имеют один метод, например, называется fly() в FlyableInterfance и quack в QuackablInterface, после чего класс Duck может реализовать методы этих интерфейсов на основе своей функции.
Таким образом, код будет рефакторизоваться следующим образом

Interface Flyable
{
    public function fly();
}
Interface Quack
{
    public function quack();
}
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь новая версия класса RubberDuck будет реализовывать новый метод интерфейса

class RubberDuck implements FlyableInterface, QuackableInterface 
{
    public function fly(){} // from interface
    public function quack(){} // from interface
    public function display(){}
}
Вход в полноэкранный режим Выйти из полноэкранного режима

и класс Duck имеет один метод, общий для всех типов, который называется display()

class Duck
{
    public function display(){}
}
Войти в полноэкранный режим Выход из полноэкранного режима

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

Оцените статью
devanswers.ru
Добавить комментарий