Omówienie aplikacji domowej – część II

Czas na omówienie kolejnej części aplikacji domowej z tygodnia 4 – czyli kolej na refaktoryzację serwisów.

Singletony

Kolejnym zadaniem w kolejce jest stworzenie singletonów z naszych serwisów – no to do dzieła.

Przypominam, że testy testujące serwisy możesz usunąć, ponieważ struktura klasy całkiem się zmienia, o czym powiem na koniec omawiania.

ProductServiceImpl

Na poczatku musimy usunąć listę produktów – nie będzie nam już potrzebna, ponieważ zastąpi ją klasa ProductDao odpowiedzialna za relację z bazą danych, którą właśnie symulowała owa lista.

Czyli musimy zostawić konstruktor bezparametrowy – prywatny – oraz dodać metodę getInstance, aby nasza klasa była singletonem.

private static ProductServiceImpl instance = null;

private ProductServiceImpl() {
}

public static ProductServiceImpl getInstance() {
    if (instance == null) {
        instance = new ProductServiceImpl();
    }

    return instance;
}

Dzięki temu, metoda getInstance zawsze zwróci ten sam obiekt.

UserServiceImpl

To samo robimy z klasą UserServiceImpl, wygląda ona identycznie jak jej poprzednik.

private static UserServiceImpl instance = null;

private UserServiceImpl() {
}

public static UserServiceImpl getInstance() {
    if (instance == null) {
        instance = new UserServiceImpl();
    }
    return instance;
}

I w taki o to sposób i ta klasa została singletonem. 😉

DAO

Skoro usunęliśmy listy z serwisów to musimy dodać pola odpowiedzialne za relację z bazą danych.

W przypadku UserServiceImpl wygląda to tak:

private UserDao userDao = UserDaoImpl.getInstance();

W końcu UserDao jest również singletonem.

No i jeszcze ProductServiceImpl:

private ProductDao productDao = new ProductDaoImpl("products.data", "PRODUCT");

Póki co ProductDaoImpl nie jest singletonem, dlatego póki co na “sztywno” ustawiamy nazwę pliku oraz typ produktu.

Walidacja

Skoro wczesniej stworzyliśmy UserValidator to warto byłoby go użyć własnie w UserServiceImpl, dlatego musimy również dodać walidator jako pole w klasie.

private UserValidator userValidator = UserValidator.getInstance();

Dzięki temu, w całej klasie możemy teraz korzystać z wcześniej stworzonego walidatora.

Skoro jest już utworzony walidator to musimy go użyć w metodzie addUser – jeśli wszystko będzie okej to użytkownik zostanie dodany do pliku, jeśli zaś nie to zostanie rzucony odpowiedni wyjątek z klasy walidującej – UserValidator.

public void addUser(User user) throws IOException, UserShortLengthPasswordException, UserLoginAlreadyExistException, UserShortLengthLoginException {
    if (userValidator.isValidate(user)) {
        userDao.saveUser(user);
    }
}

Może nasuwać się jedno pytanie – czy walidacji nie można być zrobić od razu w serwisie, albo w klasie Dao?

Jednak od razu chcę przypomnieć Ci jedną z poprzednich lekcji, w której mówiłem Ci o zasadzie jednej odpowiedzialności. Dzieląc aplikację w taki sposób jaki Ci pokazałem kod będzie czytelniejszy, ponieważ zachowujemy zasadę, gdzie każda klasa jest odpowiedzialna za określoną czynność.

Singleton UserDao

Szóstym zadaniem jest utworzenie singletonu z klasy UserDaoImpl. Tak naprawdę w zadaniu 5 wykorzystałem już metodę getInstance, która nie powinna jeszcze istnieć, jednak przypadkiem zamieniłem kolejnością zadania i wyszły takie kwiatki.

Jednak UserDaoImpl powinna mieć konstruktor prywatny i oczywiście metodę publiczną getInstance, która będzie zwracać jeden, konkretny obiekt.

private static final String fileName = "users.data";
private static UserDaoImpl instance = null;

private UserDaoImpl() {
    try {
        FileUtils.createNewFile(fileName);
    } catch (IOException e) {
        System.out.println("Error with file path");
        // exit zamyka całą aplikację
        System.exit(-1);
    }
}

public static UserDaoImpl getInstance() {
    if (instance == null) {
        instance = new UserDaoImpl();
    }

    return instance;
}

Podsumowanie

Chciałbym zatrzymać Cię na chwilę po tym podsumowaniu, aby trochę popatrzeć na to co zrobiliśmy.

Spójrz, że im większa jest nasza aplikacja to jej stopień skomplikowania rośnie. Trzeba myśleć o wielu rzeczach i niektóre rzeczy się mogą popsuć tworząc inny fragment kodu. Uczulam Cię na to, że programowanie to nie tylko pisanie kodu, ale również jego refaktoryzacja oraz wyszukiwanie błędu.

Na początku tworzenia klasy ProductDao nie zastanawialiśmy się dokładnie jak będzie odbywało się zapisywanie oraz wczytywanie produktów z pliku. Przez to, że mało czasu zostało poświęcone na początku planowania aplikacji to teraz trzeba poświęcić jeszcze więcej czasu, aby to naprawić. I zrobić to dobrze. Dlatego w następnych tygodniach będziemy naprawiać właśnie tą klasę. 😉

Aktualny stan aplikacji możesz zobaczyć tutaj.

 

Kamil Klimek

Od 2016 jestem programistą Java. Przez pierwsze 4 lata pracowałem jako Full Stack Java Developer. Później postanowiłem postawić nacisk na Javę, żeby jeszcze lepiej ją poznać.

Subscribe
Powiadom o
guest
2 komentarzy
najstarszy
najnowszy oceniany
Inline Feedbacks
View all comments
Paweł Dębiński
Paweł Dębiński
5 lat temu

Kiedy dalsza część? 🙂

Kamil Klimek
Kamil Klimek
5 lat temu

Niestety miałem dużo zaległości do nadrobienia po urlopie, jednak część o fasadach pojawi się na pewno jutro. 😉

2
0
Would love your thoughts, please comment.x