С++ Паттерн проектированя "Фабричный метод". (Продолжение)

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

Фабричный метод — это один из паттернов проектирования.
Классу заранее неизвестно, объекты каких подклассов ему нужно создавать.

Например есть класс Природа, который имеет свои подклассы: Человек, Животное, Растение.
Классу Природа может быть нужно создать объект тип которого любой из этих подклассов. Заранее неизвестно, какой из трёх.
В разных местах программы может быть необходимость приблизительно такого вида конструкции:

В какой-то момент времени требуется добавить какой-то новый тип в понятия природы, например, тип микроб, тогда нужно "прочесать" все функции и везде добавить этот тип, а это много работы, много кода, следовательно легко ошибиться и где-то пропустить добавление, удаление или исправление.

Вовнутрь любой функции в какой-то момент времени подаётся указатель на объект типа Природа, где этот указатель может указывать на любой подтип класса Природа. Работа с принятым таким образом параметром, благодаря полиморфизму, вполне себе нормальная. Объект сам поймёт к какому подтипу он относится.

Но что, если нужно создать объект во время работы функции? Вот если на вход подан отсыл на животное, то создать внутри функции объект типа животное и вернуть указатель на тип животное, а если отсыл на человека, то создать внутри функции объект типа человек и вернуть указатель на человека, то что? Указатель-то там очень старается показать, что тип объекта своего он знает и выбирает всё в соответствиях тому типу, а мы тип объекта, на который указатель указывает, знаем? Можно создать указатель на Nature, но это не то. Ведь нужно создавать объект подтипа Nature, а не типа Nature да и класс Nature абстрактный (нам должен быть не доступный). Класс Nature как и мы не знает какого подтипа нужно создать объект. Ну а какого типа new Вы предлагаете? Какой тип должна возвращать создающая объект функция?

На помощь приходит фабричный метод. Это то самое оно; это то, что он даёт; это то, ради чего он существует; это то, зачем он нужен; это то, почему он описывается в паттернах.

Что у нас есть?
Есть класс, а у него какие-то подтипы.

Что нам надо?
Нужно наплодить этих подтипов немереное количество, да ещё и в случайном каком-то порядке (не совсем случайном конечно, порядок зависим от типов, приходящих вовнутрь функции, в каком порядке типы приходят, в том и создаются, а так как прийти могут в любом порядке, то получается, что в случайном). Заранее известно, когда нужно создавать объект, но неизвестен его тип.

Способ решения?
Фабричный метод.

Как это выглядит в коде?
Я буду использовать классический способ.

  1. Создаём новый класс, который возьмёт на себя обязанности руководителя производством. Кто управляет природой? Бог, наверное, но мы обойдёмся более стандартным и понятным названием Factory;

Класс Фабрика общий, потому что какого типа объект будет создаваться изначально — неизвестно. Это "руководящий класс", он сам ничего делать не будет, а только укажет на основные процессы, существующие в его производстве.

  • 2. Создаём производство. Руководитель есть, производства как такового нет.

Обратите внимание, что внутри нашего названного производства как раз создаются объекты подтипов основного класса (не фабричного, а исходного).
return-ом возвращаются два типа указателей: на тип Man (человек) и на тип Animal (животное); Эти типы являются подтипом класса Природа.
Сколько у класса Nature подтипов, объекты, которых предполагается создавать (генерировать), столько и нужно создать классов для производства, по аналогии.

Вот и вся хитрость фабричного метода. Создали какой-то обобщённый класс (руководитель-инструктор) и создали от него производные классы для каждого создаваемого подтипа (само производство). Это важно, что для каждого. Сколько подтипов — столько и производящих, так скажем, станков.

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

Здесь опасность представляет утечка. В данном примере утечки нет. Я, изучая эту тему, столкнулся со множеством сайтов, где об утечке вообще не заботятся. Терять адреса ни в коем случае нельзя. Любым способом эти адреса нужно куда-то сохранять, чтобы корректно удалить. По этой причине у меня использованы несколько указателей, на некоторых сайтах примеры с записью указателей в массив. Это важно понимать, что указатель на начало выделенной однажды памяти легко может убежать на другой адрес, после чего тот, предыдущий адрес, куда он указывал, уже будет невозможно найти.

Чем лучше вы понимаете полиморфизм — тем проще вам будет понять, как это так получилось. Если вы не осилили ещё полиморфизм, то для изучения этой темы ваше время ещё не пришло. Здесь практически всё самое важное построено на полиморфизме.

Один комментарий на «“С++ Паттерн проектированя "Фабричный метод". (Продолжение)”»

  1. Анастасия:

    Супер, мне очень понравилось, для базового, начального понимая этого паттерна, спасибо!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/irina-kozlova/programmirovanie/?lfrom=15589587
Яндекс.Метрика