Wzorzec fabryki
Część sekcji Programowanie obiektowe ścieżki C w Coddy. Lekcja 55 z 61.
Wzorzec fabryki centralizuje tworzenie obiektów w jednej funkcji. Zamiast rozrzucać kod malloc i inicjalizacji po całym programie, wywołujesz jedną funkcję, która decyduje, co utworzyć, i zwraca gotowy do użycia obiekt.
Ten wzorzec jest szczególnie przydatny w połączeniu z polimorfizmem. Fabryka może zwracać różne typy konkretne za pomocą wspólnego wskaźnika bazowego, ukrywając przed wywołującym szczegóły tworzenia. Wywołujący prosi po prostu o „kształt”, a fabryka decyduje, czy utworzyć koło, prostokąt, czy coś innego.
Oto typowa implementacja wzorca fabryki:
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;
}
}Fabryka przyjmuje identyfikator (zwykle wyliczenie) i używa instrukcji switch, aby określić, który konstruktor wywołać. Zwraca Shape* niezależnie od utworzonego rzeczywistego typu. Wywołujący nie musi znać Circle ani Rectangle. Po prostu pracuje z typem bazowym:
Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s); // wywołanie polimorficzne
free_shape(s);Ten wzorzec ułatwia dodawanie nowych typów: wystarczy dodać nową wartość wyliczeniową i nową gałąź w fabryce. Reszta kodu pozostaje bez zmian.
Wyzwanie
ŁatwyZbudujmy fabrykę zwierząt: system, który tworzy różne rodzaje zwierząt za pomocą jednej funkcji fabrykującej. Zamiast rozpraszać logikę tworzenia w całym kodzie, skupisz ją w jednym miejscu, które na podstawie identyfikatora wejściowego decyduje, jaki rodzaj zwierzęcia utworzyć.
Podzielisz kod na trzy pliki:
pet.h: Zdefiniuj wyliczeniePetTypez wartościamiPET_DOG,PET_CATiPET_BIRD. Utwórz bazową strukturęPet, która zawiera wskaźnik na funkcjęspeak(przyjmującąconst Pet*i niczego niezwracającą). Zadeklaruj funkcję fabrykującącreate_pet, która przyjmujePetTypei zwracaPet*, a także funkcjęfree_petdo sprzątania.pet.c: Zdefiniuj trzy konkretne struktury zwierząt:Dog,CatiBird, z których każda osadzaPetjako swój pierwszy element. Zaimplementuj funkcję mówienia dla każdego typu:- Psy wypisują:
Woof! - Koty wypisują:
Meow! - Ptaki wypisują:
Tweet!
create_pet: użyj instrukcji switch dlaPetType, aby wywołać właściwy konstruktor i zwrócić wynik jakoPet*. Dla nieprawidłowych typów zwróćNULL. Zaimplementujfree_pet, aby zwolnić przydzieloną pamięć.- Psy wypisują:
main.c: Wczytaj liczbę całkowitą reprezentującą rodzaj zwierzęcia (0 dla psa, 1 dla kota, 2 dla ptaka). Użyj fabryki, aby utworzyć odpowiednie zwierzę, wywołaj jego funkcjęspeakpolimorficznie za pośrednictwem wskaźnika bazowegoPet*, a następnie zwolnij pamięć zajmowaną przez zwierzę.
Program otrzyma jedno wejście: liczbę całkowitą określającą, które zwierzę utworzyć.
Przykładowe wyjście dla wejścia 0:
Woof!Przykładowe wyjście dla wejścia 1:
Meow!Przykładowe wyjście dla wejścia 2:
Tweet!Zaletą wzorca Fabryka jest to, że main.c nie musi znać struktur Dog, Cat ani Bird. Korzysta wyłącznie z bazowego typu Pet. Dodanie później nowego rodzaju zwierzęcia oznacza dodanie nowej wartości wyliczenia i nowej gałęzi w fabryce, bez zmieniania kodu, który korzysta ze zwierząt.
Spróbuj swoich sił
#include <stdio.h>
#include "pet.h"
int main(void) {
int type;
scanf("%d", &type);
// TODO: Użyj fabryki, aby utworzyć odpowiednie zwierzę
// Wskazówka: Rzutuj int na PetType
// TODO: Wywołaj funkcję speak polimorficznie za pośrednictwem wskaźnika Pet*
// TODO: Zwolnij pamięć zajmowaną przez zwierzę
return 0;
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania modularnego
Pliki nagłówkoweZabezpieczenia przed wielokrotnym dołączeniemPliki źródłoweFunkcje statycznePodsumowanie: kalkulator modularny4Enkapsulacja
Koncepcja niejawnych wskaźnikówDefiniowanie niejawnych strukturGettery i setteryWalidacja w setterachPowtórka: tajemnicze pudełko2Obiekty i metody
Struktury jako obiektyWskaźnik „self”Poprawność constWskaźnik czy wartośćMetody pomocniczePodsumowanie: menedżer punktów5Projekt: Proste konto bankowe
Konfiguracja projektuImplementacja konta8Polimorfizm
Wskaźniki do funkcji w strukturachSymulowanie metodKoncepcja interfejsuImplementowanie interfejsówIteracja polimorficznaPodsumowanie: Greeter11Wzorce projektowe w C
Wzorzec SingletonWzorzec fabrykiWzorzec iteratoraPodsumowanie: fabryka loggera3Cykl życia obiektu
Wzorzec konstruktoraWzorzec destruktoraInicjalizacja na stosieKopia głębokaPodsumowanie: klasa opakowująca ciąg znaków6Dziedziczenie przez kompozycję
Osadzanie strukturZasada pierwszego elementuDostęp do elementów klasy nadrzędnejKonwersja w górę hierarchiiPodsumowanie: hierarchia kształtów9Projekt: Rysownik kształtów
Przegląd projektuImplementacja kołaImplementacja prostokątaZastosowanie polimorfizmuKontener kształtówPoćwicz samodzielnie: Kompilator C online