Jaki wzorzec projektowy zastosować?

0

Witam,

Uczę się poprawnie stosować wzorce. Największym na razie problemem jest dla mnie zidentyfikowanie jaki wzorzec odpowiada dokładnie mojej sytuacji...
Mam taki przykład "ćwiczebny"

  1. potrzebuję stworzyć mechanizm, który będzie zwracał mi obiekt pracownika dla podanych kryteriów wyszukiwania (w bazie danych).
  2. Obiekt ten będzie wykorzystywany zawsze w taki sam sposób.
  3. Kryteria wyszukiwania mają bezpośredni wpływ na sposób szukania (rodzaj zapytania) pracownika w bazie danych
  4. Nie interesuje mnie w jaki sposób znaleziono pracownika, mam dostać albo obiekt albo informacje, ze nie można znaleźć np. w postaci wyjątku
  5. Mechanizm powinien zapewniać buforowanie / cacheowanie aby pobieranie kilka razy tego samego pracownika nie powodowało niepotrzebnych zapytań do bazy

Dla takich wymagań próbowałem wymyślić sposób na "poprawne" zaimplementowanie tego.
Wymyśliłem że:

zrobię interfejs pracownika:

public interface IPracownik {
       int iD();
       String name();
       Date bornDate();
       // itd.
}

Stworzę jakąś klasę abstrakcyjną, która implementuje ten interfejs

public abstract class AbsPracownik implements IPracownik {
  
}  

Następnie stworzę klasy dziedziczące z AbsPracownik, które będą "wiedziały" jak się stworzyć na podstawie konkretnego kryterium wyszukiwania:

public class PracownikZPesel extends AbsPracownik {
  public PracownikZPesel( Pesel ){};
}

public class PracownikZNip extends AbsPracownik {
  public PracownikZNip( Nip ) {};
}

public class PracownikZDowod extends AbsPracownik {
  public PracownikZDowod( NrDowodu ) {};
}

Żeby zapewnic buforowanie i gdzies decydowac o tym jaki obiekt utworzyc musze miec jeszcze jedną klasę

public class Pracownicy {

  public Pracownicy() {};
  
  public IPracownik znajdzPracownika( CKryteria Kryterium ) {
    AbsPracownik Pracownik;
    
    //najpierw musze jeszcze przeszukac bufor. jesli znajde czlowieka to go zwracam. 

    switch (Kryterium.Typ) {
      case "Pesel":  Pracownik = new PracownikZPesel(Kryterium.Pesel);
      case "Nip":     Pracownik = new PracownikZNip(Kryterium.Nip);
      case ...:
    }
    ...
    return Pracownik;
    
  }

}

Czy to co wymyśliłem ma jakikolwiek sens?
Czy dobrze próbuję zaimplementować wzorzec Factory Method?
Zastanawiam się jaka w tym konkretnym przypadku byłaby różnica gdybym zamiast factory użył wzorca Template Method.
Czy buforowanie mogę zaimplementować po prostu jako tablicę obiektów, którą będę przeszukiwał?

Dziękuję z góry za pomoc.
pozdrawiam
mrlestat

0

Ten interfejs jest tu bez sensu. Przecież on dubluje to co masz w klasie abstrakcyjnej.
Jeśli to jest metoda znajdźPracownika() to to nie jest Factory bo factory zajmuje się tworzeniem. To co napisałeś to jest Factory, bo tworzysz obiekty na podstawie kryteriów oczywiście, ale nazwa metody jest zła.
Gdybyś szukał obiektów w bazie to prędzej widziałbym tu DAO a nie Factory.
Template Method to jest ZUPEŁNIE inny wzorzec i nie bardzo rozumiem jak chciałbyś je tutaj porównać ;] Template method sprawdza się w takiej sytuacji:

Masz pewien proces który przebiega zawsze tak samo, ale jest zależny od pewnych rzeczy. Np. metoda służaca do kopiowania plików określonego typu -> zawsze polega na przeglądnięciu wszystkich plików w katalogu i skopiowaniu tylko tych wybranych. Załóżmy że chcesz napisać sobie zestaw klas do kopiowania plików txt, xml i html. W zwiazku z tym piszemy sobie klasę abstrakcyjną:

class AbstractCopyClass{
  private boolean exclude(String filename); // ta metoda nie ma implementacji!
  public void copyDirectory(){
    //przeglądamy pliki i aktualny plik mamy w fileName
    if(exclude(fileName)){
      continue;
    }else{
    //kopiujemy
    }
  }
}

A potem piszemy 3 klasy które z niej dziedziczą i implementuja tylko metodę exclude()

0

Dziękuję za szczegółową odpowiedź :)

Z template chodziło mi tylko o to, ze w zasadzie dla tego trywialnego problemu implementacje poszczególnych klas różnią się tylko samym zapytaniem do bazy danych (inny select oraz inne parametry przekazywane w select ) dlatego myślałem, że stworzę jedna klasę i metodę podbierzDane() i ta metoda będzie w środku wywoływać metodę przygotujzapytanie(). Tą metodę implementowałbym w klasach dziedziczących "wpychając" odpowiednie zapytanie do wspólnego algorytmu przetwarzania danych. Tylko w takim wypadku nie mógłbym tego zrobić w konstruktorze, bo nie można wołać metod redefiniowanych w nadklasie (przynajmniej w abapie). a to burzy mój koncept, że obiekt powstaje tylko wtedy kiedy istnieją dane w bazie.

Odnośnie nazwy metody fabrykującej. czy nazewnictwo jest aż tak ważne? czy "niewłaściwa" nazwa metody kłóci się z projektowaniem poprzez wzorce?

pozdrawiam
mrlestat

0

Niewłaściwe nazwy kłócą się z logiką i utrudniają analizowanie kodu. Kiedy ktoś widzi metodę znajdź() to zakłada prędzej ze to ServiceLocator a nie Factory.

1 użytkowników online, w tym zalogowanych: 0, gości: 1