Factory Method = Metoda fabryczna.
Zadanie programistyczne
Smoki musza zapisywać wiadomości. Wiadomość może być zapisywana do wielu
różnych celów (dzienników) w różny sposób. Należy zautomatyzować wybór jednej z form zapisu
Realizacja
Interface Dziennik
zawiera jedna metodę wpisz()
.
Klasy Brudnopis
i KronikaSmokow
implementują ten interfejs i metodę
wpisz()
.
Często w praktyce aplikacja wykorzystująca obiekty implementujące interfejs
Dziennik
może nie wiedzieć, który z obiektów Brudnopi
s albo KronikaSmokow
utworzyć.
Może to zależeć od kontekstu aplikacji, wymagań użytkownika, konfiguracji sprzętu etc.
W pliku Dekret.properties określone jest czy wypisanie informacji ma być
do kroniki czy do brudnopisu w zależności czy parametr Zapis
jest TAK
czy
NIE
.
Automatyzacja wyboru następuje w klasie DziennikFactory
, która zawiera dwie metody:
jedną, określająca wartość parametru i druga będąca tzw. Factory Method, która
w zależności od wartości parametru określa której klasy obiekt zostanie utworzony.
Typ zwracany to typ interfejsu Dziennik
. Ponieważ jest to typ interfejsowy
obiekt faktycznie utworzony może należeć do dowolnej klasy implementującej ten
interfejs. W tym wypadku tworzony jest obiekt Brudnopis
, a jego
metoda wpisz
wpisuje informacje do Brudnopisu
(na konsole)
Factory Method
jest szczególnie wygodne jeśli mamy do wyboru obiekty wielu
różnych klas implementujących ten sam interfejs.
Typy
Interface Dziennik
package factorymethod; public interface Dziennik { void wpisz(String zapis); }
Klasa Brudnopis
package factorymethod; public class Brudnopis implements Dziennik { @Override public void wpisz(String zapis) { System.out.println(zapis); } }
Klasa KronikaSmokow
package factorymethod; public class KronikaSmokow implements Dziennik { @Override public void wpisz(String wpis) { Util.writeToFile("designpatterns/src/assets/KronikaSmokow.txt", wpis); } }
Klasa Util
package factorymethod; import java.io.*; class Util { private Util() { } public static boolean writeToFile(String nazwaPliku, String wiad) { DataOutputStream dos; try { File plik = new File(nazwaPliku); dos = new DataOutputStream(new FileOutputStream(plik, true)); dos.writeBytes(wiad); dos.close(); } catch (IOException ex) { return (false); } return (true); } }
Klasa DziennikFactory
package factorymethod; import java.io.*; import java.util.*; class DziennikFactory { private boolean czyZezwolonoNaZapis() { Properties p = new Properties(); try { p.load(ClassLoader .getSystemResourceAsStream("designpatterns/src/assets/Dekret.properties")); String prop = p.getProperty("Zapis"); return prop.equalsIgnoreCase("TAK"); } catch (IOException e) { return false; } } //Factory Method public Dziennik getDziennik() { if (czyZezwolonoNaZapis()) { return new KronikaSmokow(); } else { return new Brudnopis(); } } }
Klasa Main
package factorymethod; class Main { public static void main(String[] args) { DziennikFactory factory = new DziennikFactory(); Dziennik dziennik = factory.getDziennik(); dziennik.wpisz("Wydarzenie 1"); } }
Wynik
Wydarzenie 1
Uwagi
Folder assets jest umieszczony bezpośrednio w src
Plik Dekret.properties zawiera zapis Zapis=NIE
.
Należy dopracować sposób dopisywania informacji do Kroniki Smoków oraz kodowanie pliku zawierającego
Kronikę.