Ten wpis będzie dotyczył kolejnego ze wzorców projektowych z kategorii wzorców konstrukcyjnych – Matoda Wytwórcza (ang. Factory Method).
Factory Method
Wzorzec ten udostępnia interfejs do tworzenia obiektów, gdzie samym utworzeniem zajmują się podklasy.
Składowe:
- Product – jest interfejsem obiektów generowanych przez metodę wytwórczą. Może być interfejsem lub klasą abstrakcyjną.
- ConcreteProduct – implementuje interfejs klasy Product.
- Creator – zawiera w sobie bazową metodę wytwórczą która zwraca domyślny typ produktu, czyli obiekt typu Produkt. Można tu również zaimplementować rozwiązanie pozwalające na wybranie konkretnego kreatora w zależności od podanego parametru.
- ConcreteCreator – przesłania bazową metodę wytwórczą w kreatorze. Zwraca pożądany obiekt typu ConcreteProdukt.
Poniżej znajduje się diagram obrazujący jak to mniej więcej wygląda
By Trashtoy – My own work written with text editor., Domena publiczna, Link
Zastosowanie:
- Metody wytwórcze są stosowane w wielu pakietach narzędziowych.
- Można oprzeć na nich system obsługi wtyczek w aplikacji.
- Gdy ciężko jest przewidzieć jakiej klasy mają być wytworzone obiekty.
- Jeżeli chcemy, aby to podklasy danej klasy określały tworzone obiekty.
Przykładowy kod
- Tworzymy sobie część odpowiedzialną za nasz Product i ConcreteProdukt, czy interfejs IArchive oraz klasy ZipArchive i RarArchive
public interface IArchive { void ChooseLibrary(); } class ZipArchive : IArchive { public void ChooseLibrary() { Console.WriteLine("I chooses ZIP library to make a zip file"); } } class RarArchive : IArchive { public void ChooseLibrary() { Console.WriteLine("I chooses RAR library to make a rar file"); } }
- Teraz kolej na nas Creator. Będzie on również posiadał statyczną metodę wybierającą ConcreteProduct na podstawie przekazanego parametru. W tym przypadku enuma ArchiveType
public abstract class Creator { public enum ArchiveType { RAR, ZIP, } public abstract IArchive CreateArchive (); public static Creator CreateCreator (Creator.ArchiveType type) { switch (type) { case ArchiveType.RAR: return new RarCreator (); case ArchiveType.ZIP: return new ZipCreator (); default: return null; } } }
- Nadeszła kolej na nasze ConcreteProducts, które przesłaniają metodę metody wytwórczej
public class RarCreator : Creator { public override IArchive CreateArchive () { return new RarArchive (); } } public class ZipCreator : Creator { public override IArchive CreateArchive () { return new ZipArchive (); } }
- Nie pozostaje nic innego jak sprawdzenie, czy wszystko działa tak jak tego oczekujemy
class Program { static void Main (string[] args) { Creator creator = Creator.CreateCreator(Creator.ArchiveType.RAR); IArchive archive = creator.CreateArchive(); archive.ChooseLibrary(); Console.WriteLine("-----------------------"); creator = Creator.CreateCreator(Creator.ArchiveType.ZIP); archive = creator.CreateArchive(); archive.ChooseLibrary(); Console.ReadLine(); } }
Wynikiem w konsoli będzie:
I chooses RAR library to make a rar file
———————–
I chooses ZIP library to make a zip file