Konstrukcyjny wzorzec projektowy Fabryki w C#
- Kategoria: Programowanie, Tagi: .Net, C#, Wzorce
- Napisane przez: Jerzy Piechowiak
- Liczba odsłon: 5016
W świecie informatyki, zaprogramować można wszystko. Ponadto, każdy problem, czy zagadnienie ma tysiące rozwiązań (a może nawet tyle co programistów na świecie:)). Niektóre problemy - zagadnienia, powtarzają się na tyle często, że pewne mądre głowy opracowały gotowe sposoby, wzorce rozwiązań takich problemów. Kiedyś opisywałem już wzorzec projektowy Model View Controller. Dziś, chciałbym zaprezentować wzorzec projektowy Factory (z ang. fabryki), ułatwiający tworzenie nowych obiektów.
Przykłady zaprezentowane w niniejszym artykule, przygotowane zostały w języku C#. Nic nie stoi jednak na przeszkodzie, by wykorzystać je w innym języku programowania:)
Idea wzorca projektowego Fabryki
Wzorzec projektowy Fabryki, pozwala na tworzenie obiektów w inteligenty sposób. Idea takiego wzorca może prezentować się następująco. Stworzyliśmy interfejs, posiadający określoną metodę, którą każda z klas go implementujących powinna wypełnić na swój określony sposób. Następnie, chcielibyśmy posiadać klasę z metodą tworzącą nasze obiekty w sposób automatyczny. Dzięki temu, w dalszym etapie użytkownik będzie mógł skorzystać z metody wymuszonej przez interfejs, ale na różne sposoby, niekoniecznie będąc tego świadomym:) Będzie to oczywiście zależne od przekazanych danych wejściowych. Mogło to zabrzmieć trochę zawile, ale tak naprawdę powinno rozjaśnić się po przykładzie.
Czas więc, rozpocząć prace programistyczne. Rozpoczniemy je od napisania interfejsu dla naszych pięknych klas:)
Tworzymy interfejs
Nasz interfejs będzie bajecznie prosty. Posiadać będzie deklarację jednej metody, która odpowiedzialna będzie.. za wydawanie dźwięków określonych zwierząt:)
interface IAnimal
{
void MakeSound();
}
Klasy dla interfejsu
Aby nasz interfejs nie czuł się samotny i nie potrzebny, dopiszemy kilka klas, które okrutnie go wykorzystają...
class CCat : IAnimal
{
#region IAnimal Members
public void MakeSound()
{
Console.WriteLine("Miauuuu!");
}
#endregion
}
class CDog : IAnimal
{
#region IAnimal Members
public void MakeSound()
{
Console.WriteLine("Hauuuu!");
}
#endregion
}
class CWolf : IAnimal
{
#region IAnimal Members
public void MakeSound()
{
Console.WriteLine("Auuuu!");
}
#endregion
}
Mamy tutaj jak widać niezły zwierzyniec. Wszystkie trzy nasze nowe klasy implementują ten sam interfejs (IAnimal) i wypełniają te samą metodę (MakeSound), ale oczywiście każda na swój, zwierzęcy charakterystyczny sposób.
Enumeracja dla zwierzątek
Za poradą użytkownika @rek, utworzymy enumerację, która pozwoli na łatwiejsze rozpoznawanie naszych zwierzątek i uniknięcie błędów podczas tworzenia kodu.
enum Animals
{
Cat, Dog, Wolf
}
W przyszłości można z powodzeniem tutaj dodać nowe zwierzaki:)
Tworzymy klasę fabrykującą
Żeby teraz nasze zwierzątka nie poczuły się niepotrzebne, musimy stworzyć klasę fabrykującą z odpowiednią metodą.
class CAnimalFactory
{
public IAnimal CreateAnimalObject(Animals eAnimalType)
{
IAnimal oAnimal = null;
switch (eAnimalType)
{
case Animals.Cat:
oAnimal = new CCat();
break;
case Animals.Dog:
oAnimal = new CDog();
break;
case Animals.Wolf:
oAnimal = new CWolf();
break;
}
return oAnimal;
}
}
Stworzyliśmy piękną klasę fabrykującą, wraz z odpowiednią metodą. Zasada działania jest prosta. Do naszej metody, przekazujemy typ zwierzęcia (wykorzystujemy do tego wcześniej utworzoną enumerację). Najpierw zapisujemy deklarację obiektu, na początku będącą nullem. Potem, w zależności od przekazanego typu zwierzęcia, tworzymy instancję określonej klasy i przypisujemy ją do naszego dotychczas pustego obiektu. Na końcu zwracamy referencję do interfejsu (czyli właśnie utworzonego obiektu, lub nie, gdy żaden obiekt nie pasuje do zadeklarowanego typu. Wtedy zwracamy nulla).
Testowanie kodu
Aby przetestować nasz piękny kod, stworzę teraz klasę aplikacji konsolowej z metodą main.
class CProgram
{
static void Main(string[] args)
{
CAnimalFactory oAnimalFactory = new CAnimalFactory();
IAnimal oAnimal = oAnimalFactory.CreateAnimalObject(Animals.Dog);
if(null != oAnimal)
{
oAnimal.MakeSound();
}
}
}
Nasz programik, jak widać skomplikowany nie jest. Tworzymy obiekt klasy CAnimalFactory, następnie korzystamy z metody CreateAnimalObject przekazując do niej odpowiedni typ zwierzaka. W efekcie dostajemy obiekt, który na pewno dziedziczy po interfejsie IAnimal. Na koniec, możemy wydać dźwięk z obiektu naszego zwierzaka. O tym jaki będzie to odgłos, to sugeruję się już przekonać osobiście:)
Poprawki...
Napisany tutaj kod, nie jest jednak taki piękny. Największą jego bolączką, to chyba brak klauzuli default w instrukcji switch. Co prawda obsługujemy sytuację, kiedy zwrócona referencja jest nullem i w sumie jest to jakaś opcja, ale można by o tym defaulcie też jakoś pomyśleć.
Dodatkowo, metodę CreateAnimalObject można by uczynić statyczną, aby uniknąć tworzenia kolejnego obiektu. Aczkolwiek nie jest to konieczne:)
Data ostatniej modyfikacji: 31.07.2011, 13:32.
Komentarze