Fabryka

Wzorzec fabryki należy do grupy wzorców konstrukcji tzn takich, które mają za zadanie dostarczyć nam nowych obiektów. W języku java, najprościej utworzyć obiekt za pomocą operatora new. Operator przedstawiony nam został w przeszłości bardzo ciepło, jako operator tworzący instancję klasy. Operator najczęściej poznawaliśmy w książkach w rozdziałach o obiektowości. Mi kojarzył się z rycerzem na białym koniu, który rozpędza ciemność programowania proceduralnego.

Formularz form = new Formularz();

Kawałek kodu powyżej prezentuje zastosowanie tego operatora.

Za pomocą powyższego kodu utworzyliśmy instancję klasy Formularz. Nowa instancje ma początkowe wartości ustawione przez konstruktor jest wspaniale używamy obiektowości, ale ten kawałek kodu ma kilka wad:

  1. Na stałe zadeklarowaliśmy w kodzie że w tym miejscu utworzymy Formularz. Przecież mogło by być tak że po klasie Formularz dziedziczą inne klasy np: BankowyFormularz, SkarbowyFormularz, MieszkaniowyFormularz. Program mógłby generować (dawać, dostarczać, tworzyć) nowy formularz w zależności od zmieniającego się stanu programu.
  2. Możemy założyć, że chcemy przed ostatecznym “wydaniem” formularza powiększyć czcionkę dla osób z gorszym wzrokiem a dla osób z lepszym wzrokiem czcionkę pozostawić bez zmian. Załóżmy też że kawałek kodu powyżej nie jest jedynym takim kawałkiem w programie. Wtedy musimy dodać w kilku miejscach w programie if-y, które sprawdzą wzrok użytkownika. Już nie mówię o sytuacji, gdy będziemy później chcieli z tego warunku zrezygnować i wyszukać te wszystkie if-y by je skasować.

Podstawowym problem jest to, że obiekt który tworzymy jest zahardkodowany i jedyny sposób na utworzenie innego nowego obiektu to zmiana kodu.

Przyjrzyjmy się przykładowi zastosowania Fabryki na prostym programie.
Zakładamy, że mamy napisać program do generowania formularzy w swingu na podstawie pliku wejściowego (Na początek przyjmijmy że to plik xml). Każdy element xml-a będzie określał inny komponent. Komponenty dziedziczą po klasie JPanel — Klasa bazowa dla naszych komponentów.
Tag “pytanie” — ma za zadanie utworzyć komponent QuestionComponet.

public class QuestionComponent extends JPanel {
    private JButton yesButton;
private JButton noButton;
    public QuestionComponent() {
yesButton = new JButton("YES");
noButton = new JButton("NO");
add(yesButton);
add(noButton);
}
}

Tag “label” — ma za zadanie utworzyć komponent LoginComponent.

public class LoginComponent extends JPanel {
    private String label;
private String text;
private JLabel jlabel;
private JTextField textField;
private JButton button;
    public LoginComponent(String label, String text) {
this.label = label;
this.text = text;
jlabel = new JLabel(this.label);
textField = new JTextField(this.text);
JPanel panel = new JPanel();
panel.add(jlabel);
panel.add(textField);
button = new JButton("OK");
add(panel);
add(button);
}
}

Tag “ok” — ma za zadanie utworzyć przycisk potwierdzenia: SuperOkComponent.

public class SuperOkComponent extends JPanel {

private JButton button;
public SuperOkComponent() {
button = new JButton("OK");
setSize(new Dimension(100, 100));
add(button);
}
}

Parser xml-a za każdym razem będzie wywoływał w formularzu metodę utworzPoleForm(String pole) z nazwą tag-u.
Duża ilość osób chcących jak najszybciej wywiązać się z zadania już w tej metodzie napisze ifologię już w tej metodzie:

public void utworzPoleForm(String pole)
{
if ("pytanie".equals(pole))
{
JPanel qc = new QuestionComponent();
add(qc);
}
if ("label".equals(pole)){
JPanel lc = new LoginComponent("label", "text");
lc.setForeground(Color.YELLOW);
add(lc);
}
if ("ok".equals(pole))
{
JPanel so = new SuperOkComponent();
so.setForeground(Color.YELLOW);
add(so);
}

Zadanie wykonane, ale nie jest rozszerzalne ani ładne, bo jeśli ktoś będzie chciał inny formularz parsować ta metodą, wtedy musimy naszą if-ologię przekopiować do innego formularza. Później gdybyśmy chcieli coś zmodyfikować musimy szukać wszystkich ifów. (Przykład modyfikacji, zamiast przycisku SuperOkComponent chcielibyśmy go zamienić we wszystkich formularzach na ExtraOkButton.)
Gdy wiemy, że nasza if-ologia generatora będzie wykorzystywana w kilku miejscach użyjmy coś co ją opakuje i pozwoli na ponowne łatwe użycie -> Klasy.

Klasa, którą napiszemy będzie miała metodę utworzPoleForm(String pole) przyjmującą jako parametr nazwę pola, które powinno być wygenerowane, a zwracać będzie klasę bazową komponentów czyli JPanel, klasę nazwiemy ProstaFabrykaKomponentow:

public class ProstaFabrykaKomponentow {


public JPanel utworzPoleForm(String pole)
{
JPanel komponent= null;
if ("pytanie".equals(pole))
{
komponent = new QuestionComponent();
}
if ("label".equals(pole)){
komponent= new LoginComponent("label", "text");
komponent.setForeground(Color.YELLOW);
}
if ("ok".equals(pole))
{
komponent= new SuperOkComponent();
komponent.setForeground(Color.YELLOW);
}
return komponent;
}
}

Teraz wszędzie tam gdzie będziemy chcieli utworzyć, jeden z komponentów skorzystajmy z fabryki. Jeśli byśmy chcieli całkowicie zmienić formularze, możemy zmienić je w jednym miejscu, czyli w prostej fabryce. Jeśli np. chcemy zmienić kolor tła komponentów, wtedy nie trzeba ich szukać po całym programie, wystarczy, że znajdziemy fabrykę i w niej zmodyfikujemy kod.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.