Паттерн Factory
Часть раздела Объектно-ориентированное программирование путешествия по C на Coddy. Урок 55 из 61.
Паттерн Factory централизует создание объектов в одной функции. Вместо того чтобы распределять malloc и код инициализации по всей программе, вы вызываете одну функцию, которая решает, что создать, и возвращает готовый к использованию объект.
Этот шаблон особенно эффективен в сочетании с полиморфизмом. factory может возвращать разные конкретные типы через общий указатель base, скрывая детали создания от вызывающего кода. Вызывающий код просто запрашивает «фигуру», а factory решает, создать ли круг, прямоугольник или что-то ещё.
Вот типичная реализация фабрики:
typedef enum {
SHAPE_CIRCLE,
SHAPE_RECTANGLE
} ShapeType;
Shape* create_shape(ShapeType type) {
switch (type) {
case SHAPE_CIRCLE:
return (Shape*)create_circle(5.0);
case SHAPE_RECTANGLE:
return (Shape*)create_rectangle(4.0, 3.0);
default:
return NULL;
}
}Фабрика принимает идентификатор (обычно enum) и использует оператор switch, чтобы определить, какой constructor вызвать. Она возвращает Shape* независимо от фактически созданного типа. Вызывающему коду не нужно знать о Circle или Rectangle. Он просто работает с базовым типом:
Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s); // полиморфный вызов
free_shape(s);Этот шаблон упрощает добавление новых типов: просто добавь новое значение enum и новый case в factory. Остальной код останется без изменений.
Задание
ЛегкоДавайте создадим Pet Factory: систему, которая создаёт разные типы питомцев с помощью одной factory function. Вместо того чтобы распределять логику создания по всему коду, вы централизуете её в одном месте, которое решает, какого питомца создать, основываясь на входном идентификаторе.
Вы организуете код в трёх файлах:
pet.h: Определите перечислениеPetTypeсо значениямиPET_DOG,PET_CATиPET_BIRD. Создайте базовую структуруPet, содержащую указатель на function дляspeak(которая принимаетconst Pet*и ничего не возвращает). Объявите factory functioncreate_pet, которая принимаетPetTypeи возвращаетPet*, а также functionfree_petдля очистки.pet.c: Определите три конкретные структуры питомцев —Dog,CatиBird, каждая из которых встраиваетPetв качестве своего первого member. Реализуйте function speak для каждого типа:- Dogs выводят:
Woof! - Cats выводят:
Meow! - Birds выводят:
Tweet!
create_pet: используйте switch statement дляPetType, чтобы вызвать correct constructor и вернуть результат какPet*. Для invalid типов вернитеNULL. Реализуйтеfree_pet, чтобы освободить Allocate memory.- Dogs выводят:
main.c: Считайте целое число, представляющее тип питомца (0 для dog, 1 для cat, 2 для bird). Используйте factory, чтобы создать appropriate питомца, вызовите его functionspeakполиморфно через указатель базового типаPet*, затем освободите питомца.
Ваша программа получит один входной параметр: целое число, указывающее, какого питомца создать.
Пример вывода, когда входное значение равно 0:
Woof!Пример вывода, когда входное значение равно 1:
Meow!Пример вывода, когда входное значение равно 2:
Tweet!Преимущество паттерна Factory заключается в том, что main.c не нужно знать о структурах Dog, Cat или Bird. Он работает только с базовым типом Pet. Добавление нового типа питомца в дальнейшем означает добавление нового значения перечисления и нового case в factory без изменения кода, использующего питомцев.
Попробуйте сами
#include <stdio.h>
#include "pet.h"
int main(void) {
int type;
scanf("%d", &type);
// TODO: Используйте фабрику, чтобы создать подходящего питомца
// Подсказка: Приведите int к PetType
// TODO: Вызовите функцию speak полиморфно через указатель Pet*
// TODO: Освободите питомца
return 0;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация кругаРеализация прямоугольникаПолиморфное использованиеКонтейнер фигурПотренируйтесь самостоятельно: Онлайн-компилятор C